forked from OSchip/llvm-project
Rename all 'EvalXXX' methods in libChecker to
'evalXXX'. llvm-svn: 120609
This commit is contained in:
parent
87240d4b9c
commit
dc891429e4
|
@ -179,7 +179,7 @@ public:
|
||||||
return SValListFactory.add(X, L);
|
return SValListFactory.add(X, L);
|
||||||
}
|
}
|
||||||
|
|
||||||
const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op,
|
const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
|
||||||
const llvm::APSInt& V1,
|
const llvm::APSInt& V1,
|
||||||
const llvm::APSInt& V2);
|
const llvm::APSInt& V2);
|
||||||
|
|
||||||
|
|
|
@ -207,20 +207,20 @@ private:
|
||||||
_PostVisit(C, S);
|
_PostVisit(C, S);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GR_EvalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
bool GR_evalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
||||||
GRExprEngine &Eng, const ObjCMessageExpr *ME,
|
GRExprEngine &Eng, const ObjCMessageExpr *ME,
|
||||||
ExplodedNode *Pred, const GRState *state, void *tag) {
|
ExplodedNode *Pred, const GRState *state, void *tag) {
|
||||||
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
|
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
|
||||||
0, ME, state);
|
0, ME, state);
|
||||||
return EvalNilReceiver(C, ME);
|
return evalNilReceiver(C, ME);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
bool GR_evalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
||||||
GRExprEngine &Eng, const CallExpr *CE,
|
GRExprEngine &Eng, const CallExpr *CE,
|
||||||
ExplodedNode *Pred, void *tag) {
|
ExplodedNode *Pred, void *tag) {
|
||||||
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
|
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
|
||||||
0, CE);
|
0, CE);
|
||||||
return EvalCallExpr(C, CE);
|
return evalCallExpr(C, CE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Remove the 'tag' option.
|
// FIXME: Remove the 'tag' option.
|
||||||
|
@ -250,12 +250,12 @@ private:
|
||||||
VisitLocation(C, S, location);
|
VisitLocation(C, S, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GR_EvalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
void GR_evalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
||||||
GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
|
GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
|
||||||
SymbolReaper &SymReaper, void *tag) {
|
SymbolReaper &SymReaper, void *tag) {
|
||||||
CheckerContext C(Dst, Builder, Eng, Pred, tag,
|
CheckerContext C(Dst, Builder, Eng, Pred, tag,
|
||||||
ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
|
ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
|
||||||
EvalDeadSymbols(C, SymReaper);
|
evalDeadSymbols(C, SymReaper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -265,8 +265,8 @@ public:
|
||||||
virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
|
virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
|
||||||
virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
|
virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
|
||||||
SVal location, SVal val) {}
|
SVal location, SVal val) {}
|
||||||
virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
|
virtual void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
|
||||||
virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
|
virtual void evalEndPath(GREndPathNodeBuilder &B, void *tag,
|
||||||
GRExprEngine &Eng) {}
|
GRExprEngine &Eng) {}
|
||||||
|
|
||||||
virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
|
virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
|
||||||
|
@ -275,15 +275,15 @@ public:
|
||||||
GRExprEngine &Eng,
|
GRExprEngine &Eng,
|
||||||
const Stmt *Condition, void *tag) {}
|
const Stmt *Condition, void *tag) {}
|
||||||
|
|
||||||
virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
|
virtual bool evalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const GRState *EvalAssume(const GRState *state, SVal Cond,
|
virtual const GRState *evalAssume(const GRState *state, SVal Cond,
|
||||||
bool Assumption, bool *respondsToCallback) {
|
bool Assumption, bool *respondsToCallback) {
|
||||||
*respondsToCallback = false;
|
*respondsToCallback = false;
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -224,7 +224,7 @@ public:
|
||||||
/// Called by GRCoreEngine when the analysis worklist has terminated.
|
/// Called by GRCoreEngine when the analysis worklist has terminated.
|
||||||
void ProcessEndWorklist(bool hasWorkRemaining);
|
void ProcessEndWorklist(bool hasWorkRemaining);
|
||||||
|
|
||||||
/// EvalAssume - Callback function invoked by the ConstraintManager when
|
/// evalAssume - Callback function invoked by the ConstraintManager when
|
||||||
/// making assumptions about state values.
|
/// making assumptions about state values.
|
||||||
const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption);
|
const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption);
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ public:
|
||||||
/// other functions that handle specific kinds of statements.
|
/// other functions that handle specific kinds of statements.
|
||||||
void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
||||||
|
|
||||||
/// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is
|
/// VisitLValue - evaluate the lvalue of the expression. For example, if Ex is
|
||||||
/// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
|
/// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
|
||||||
/// storage location. Note that not all kinds of expressions has lvalue.
|
/// storage location. Note that not all kinds of expressions has lvalue.
|
||||||
void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
||||||
|
@ -466,61 +466,61 @@ public:
|
||||||
const StackFrameContext *frameCtx);
|
const StackFrameContext *frameCtx);
|
||||||
|
|
||||||
/// Evaluate arguments with a work list algorithm.
|
/// Evaluate arguments with a work list algorithm.
|
||||||
void EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
|
void evalArguments(ConstExprIterator AI, ConstExprIterator AE,
|
||||||
const FunctionProtoType *FnType,
|
const FunctionProtoType *FnType,
|
||||||
ExplodedNode *Pred, ExplodedNodeSet &Dst,
|
ExplodedNode *Pred, ExplodedNodeSet &Dst,
|
||||||
bool FstArgAsLValue = false);
|
bool FstArgAsLValue = false);
|
||||||
|
|
||||||
/// Evaluate method call itself. Used for CXXMethodCallExpr and
|
/// Evaluate method call itself. Used for CXXMethodCallExpr and
|
||||||
/// CXXOperatorCallExpr.
|
/// CXXOperatorCallExpr.
|
||||||
void EvalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
|
void evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
|
||||||
const Expr *ThisExpr, ExplodedNode *Pred,
|
const Expr *ThisExpr, ExplodedNode *Pred,
|
||||||
ExplodedNodeSet &Src, ExplodedNodeSet &Dst);
|
ExplodedNodeSet &Src, ExplodedNodeSet &Dst);
|
||||||
|
|
||||||
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
|
/// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
|
||||||
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
|
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
|
||||||
/// with those assumptions.
|
/// with those assumptions.
|
||||||
void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
|
void evalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
|
||||||
const Expr *Ex);
|
const Expr *Ex);
|
||||||
|
|
||||||
SVal EvalMinus(SVal X) {
|
SVal evalMinus(SVal X) {
|
||||||
return X.isValid() ? svalBuilder.EvalMinus(cast<NonLoc>(X)) : X;
|
return X.isValid() ? svalBuilder.evalMinus(cast<NonLoc>(X)) : X;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVal EvalComplement(SVal X) {
|
SVal evalComplement(SVal X) {
|
||||||
return X.isValid() ? svalBuilder.EvalComplement(cast<NonLoc>(X)) : X;
|
return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
||||||
NonLoc L, NonLoc R, QualType T) {
|
NonLoc L, NonLoc R, QualType T) {
|
||||||
return svalBuilder.EvalBinOpNN(state, op, L, R, T);
|
return svalBuilder.evalBinOpNN(state, op, L, R, T);
|
||||||
}
|
}
|
||||||
|
|
||||||
SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
||||||
NonLoc L, SVal R, QualType T) {
|
NonLoc L, SVal R, QualType T) {
|
||||||
return R.isValid() ? svalBuilder.EvalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
|
return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
||||||
SVal LHS, SVal RHS, QualType T) {
|
SVal LHS, SVal RHS, QualType T) {
|
||||||
return svalBuilder.EvalBinOp(ST, Op, LHS, RHS, T);
|
return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME,
|
void evalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME,
|
||||||
ExplodedNode* Pred, const GRState *state) {
|
ExplodedNode* Pred, const GRState *state) {
|
||||||
assert (Builder && "GRStmtNodeBuilder must be defined.");
|
assert (Builder && "GRStmtNodeBuilder must be defined.");
|
||||||
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
|
getTF().evalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,
|
const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,
|
||||||
bool branchTaken);
|
bool branchTaken);
|
||||||
|
|
||||||
/// EvalBind - Handle the semantics of binding a value to a specific location.
|
/// evalBind - Handle the semantics of binding a value to a specific location.
|
||||||
/// This method is used by EvalStore, VisitDeclStmt, and others.
|
/// This method is used by evalStore, VisitDeclStmt, and others.
|
||||||
void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
|
void evalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
|
||||||
const GRState* St, SVal location, SVal Val,
|
const GRState* St, SVal location, SVal Val,
|
||||||
bool atDeclInit = false);
|
bool atDeclInit = false);
|
||||||
|
|
||||||
|
@ -531,23 +531,23 @@ public:
|
||||||
// be the same as Pred->state, and when 'location' may not be the
|
// be the same as Pred->state, and when 'location' may not be the
|
||||||
// same as state->getLValue(Ex).
|
// same as state->getLValue(Ex).
|
||||||
/// Simulate a read of the result of Ex.
|
/// Simulate a read of the result of Ex.
|
||||||
void EvalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
|
void evalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
|
||||||
const GRState* St, SVal location, const void *tag = 0,
|
const GRState* St, SVal location, const void *tag = 0,
|
||||||
QualType LoadTy = QualType());
|
QualType LoadTy = QualType());
|
||||||
|
|
||||||
// FIXME: 'tag' should be removed, and a LocationContext should be used
|
// FIXME: 'tag' should be removed, and a LocationContext should be used
|
||||||
// instead.
|
// instead.
|
||||||
void EvalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
|
void evalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
|
||||||
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
|
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
|
||||||
const void *tag = 0);
|
const void *tag = 0);
|
||||||
private:
|
private:
|
||||||
void EvalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
|
void evalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
|
||||||
const GRState* St, SVal location, const void *tag,
|
const GRState* St, SVal location, const void *tag,
|
||||||
QualType LoadTy);
|
QualType LoadTy);
|
||||||
|
|
||||||
// FIXME: 'tag' should be removed, and a LocationContext should be used
|
// FIXME: 'tag' should be removed, and a LocationContext should be used
|
||||||
// instead.
|
// instead.
|
||||||
void EvalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
|
void evalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
|
||||||
const GRState* St, SVal location,
|
const GRState* St, SVal location,
|
||||||
const void *tag, bool isLoad);
|
const void *tag, bool isLoad);
|
||||||
|
|
||||||
|
|
|
@ -39,13 +39,13 @@ public:
|
||||||
|
|
||||||
// Calls.
|
// Calls.
|
||||||
|
|
||||||
virtual void EvalCall(ExplodedNodeSet& Dst,
|
virtual void evalCall(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Engine,
|
GRExprEngine& Engine,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const CallExpr* CE, SVal L,
|
const CallExpr* CE, SVal L,
|
||||||
ExplodedNode* Pred) {}
|
ExplodedNode* Pred) {}
|
||||||
|
|
||||||
virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
|
virtual void evalObjCMessageExpr(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Engine,
|
GRExprEngine& Engine,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const ObjCMessageExpr* ME,
|
const ObjCMessageExpr* ME,
|
||||||
|
@ -54,15 +54,15 @@ public:
|
||||||
|
|
||||||
// Stores.
|
// Stores.
|
||||||
|
|
||||||
virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {}
|
virtual void evalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {}
|
||||||
|
|
||||||
// End-of-path and dead symbol notification.
|
// End-of-path and dead symbol notification.
|
||||||
|
|
||||||
virtual void EvalEndPath(GRExprEngine& Engine,
|
virtual void evalEndPath(GRExprEngine& Engine,
|
||||||
GREndPathNodeBuilder& Builder) {}
|
GREndPathNodeBuilder& Builder) {}
|
||||||
|
|
||||||
|
|
||||||
virtual void EvalDeadSymbols(ExplodedNodeSet& Dst,
|
virtual void evalDeadSymbols(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Engine,
|
GRExprEngine& Engine,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
|
@ -70,14 +70,14 @@ public:
|
||||||
SymbolReaper& SymReaper) {}
|
SymbolReaper& SymReaper) {}
|
||||||
|
|
||||||
// Return statements.
|
// Return statements.
|
||||||
virtual void EvalReturn(ExplodedNodeSet& Dst,
|
virtual void evalReturn(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Engine,
|
GRExprEngine& Engine,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const ReturnStmt* S,
|
const ReturnStmt* S,
|
||||||
ExplodedNode* Pred) {}
|
ExplodedNode* Pred) {}
|
||||||
|
|
||||||
// Assumptions.
|
// Assumptions.
|
||||||
virtual const GRState* EvalAssume(const GRState *state,
|
virtual const GRState* evalAssume(const GRState *state,
|
||||||
SVal Cond, bool Assumption) {
|
SVal Cond, bool Assumption) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,36 +31,36 @@ protected:
|
||||||
public:
|
public:
|
||||||
// FIXME: Make these protected again one RegionStoreManager correctly
|
// FIXME: Make these protected again one RegionStoreManager correctly
|
||||||
// handles loads from differening bound value types.
|
// handles loads from differening bound value types.
|
||||||
virtual SVal EvalCastNL(NonLoc val, QualType castTy) = 0;
|
virtual SVal evalCastNL(NonLoc val, QualType castTy) = 0;
|
||||||
virtual SVal EvalCastL(Loc val, QualType castTy) = 0;
|
virtual SVal evalCastL(Loc val, QualType castTy) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SValBuilder(ValueManager &valMgr) : ValMgr(valMgr) {}
|
SValBuilder(ValueManager &valMgr) : ValMgr(valMgr) {}
|
||||||
virtual ~SValBuilder() {}
|
virtual ~SValBuilder() {}
|
||||||
|
|
||||||
SVal EvalCast(SVal V, QualType castTy, QualType originalType);
|
SVal evalCast(SVal V, QualType castTy, QualType originalType);
|
||||||
|
|
||||||
virtual SVal EvalMinus(NonLoc val) = 0;
|
virtual SVal evalMinus(NonLoc val) = 0;
|
||||||
|
|
||||||
virtual SVal EvalComplement(NonLoc val) = 0;
|
virtual SVal evalComplement(NonLoc val) = 0;
|
||||||
|
|
||||||
virtual SVal EvalBinOpNN(const GRState *state, BinaryOperator::Opcode Op,
|
virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode Op,
|
||||||
NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
|
NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
|
||||||
|
|
||||||
virtual SVal EvalBinOpLL(const GRState *state, BinaryOperator::Opcode Op,
|
virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode Op,
|
||||||
Loc lhs, Loc rhs, QualType resultTy) = 0;
|
Loc lhs, Loc rhs, QualType resultTy) = 0;
|
||||||
|
|
||||||
virtual SVal EvalBinOpLN(const GRState *state, BinaryOperator::Opcode Op,
|
virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode Op,
|
||||||
Loc lhs, NonLoc rhs, QualType resultTy) = 0;
|
Loc lhs, NonLoc rhs, QualType resultTy) = 0;
|
||||||
|
|
||||||
/// getKnownValue - Evaluates a given SVal. If the SVal has only one possible
|
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible
|
||||||
/// (integer) value, that value is returned. Otherwise, returns NULL.
|
/// (integer) value, that value is returned. Otherwise, returns NULL.
|
||||||
virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V) = 0;
|
virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V) = 0;
|
||||||
|
|
||||||
SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
||||||
SVal L, SVal R, QualType T);
|
SVal L, SVal R, QualType T);
|
||||||
|
|
||||||
DefinedOrUnknownSVal EvalEQ(const GRState *ST, DefinedOrUnknownSVal L,
|
DefinedOrUnknownSVal evalEQ(const GRState *ST, DefinedOrUnknownSVal L,
|
||||||
DefinedOrUnknownSVal R);
|
DefinedOrUnknownSVal R);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -489,7 +489,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer functions for binary/unary operations on ConcreteInts.
|
// Transfer functions for binary/unary operations on ConcreteInts.
|
||||||
SVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
|
SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
|
||||||
const ConcreteInt& R) const;
|
const ConcreteInt& R) const;
|
||||||
|
|
||||||
// Implement isa<T> support.
|
// Implement isa<T> support.
|
||||||
|
|
|
@ -152,8 +152,8 @@ public:
|
||||||
const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy);
|
const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy);
|
||||||
|
|
||||||
|
|
||||||
/// EvalBinOp - Perform pointer arithmetic.
|
/// evalBinOp - Perform pointer arithmetic.
|
||||||
virtual SVal EvalBinOp(BinaryOperator::Opcode Op,
|
virtual SVal evalBinOp(BinaryOperator::Opcode Op,
|
||||||
Loc lhs, NonLoc rhs, QualType resultTy) {
|
Loc lhs, NonLoc rhs, QualType resultTy) {
|
||||||
return UnknownVal();
|
return UnknownVal();
|
||||||
}
|
}
|
||||||
|
|
|
@ -458,7 +458,7 @@ public:
|
||||||
|
|
||||||
/// isDead - Returns whether or not a symbol has been confirmed dead. This
|
/// isDead - Returns whether or not a symbol has been confirmed dead. This
|
||||||
/// should only be called once all marking of dead symbols has completed.
|
/// should only be called once all marking of dead symbols has completed.
|
||||||
/// (For checkers, this means only in the EvalDeadSymbols callback.)
|
/// (For checkers, this means only in the evalDeadSymbols callback.)
|
||||||
bool isDead(SymbolRef sym) const {
|
bool isDead(SymbolRef sym) const {
|
||||||
return TheDead.count(sym);
|
return TheDead.count(sym);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C,
|
||||||
// FIXME: Do more checking and actual emit an error. At least performing
|
// FIXME: Do more checking and actual emit an error. At least performing
|
||||||
// the cast avoids some assertion failures elsewhere.
|
// the cast avoids some assertion failures elsewhere.
|
||||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||||
V = svalBuilder.EvalCast(V, expectedResultTy, actualResultTy);
|
V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
|
||||||
C.GenerateNode(state->BindExpr(CE, V));
|
C.GenerateNode(state->BindExpr(CE, V));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -414,7 +414,7 @@ void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
|
||||||
|
|
||||||
// Make an expression asserting that they're equal.
|
// Make an expression asserting that they're equal.
|
||||||
SValBuilder &svalBuilder = ValMgr.getSValBuilder();
|
SValBuilder &svalBuilder = ValMgr.getSValBuilder();
|
||||||
DefinedOrUnknownSVal ArgIsNull = svalBuilder.EvalEQ(state, Zero, *DefArgVal);
|
DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, Zero, *DefArgVal);
|
||||||
|
|
||||||
// Are they equal?
|
// Are they equal?
|
||||||
const GRState *stateTrue, *stateFalse;
|
const GRState *stateTrue, *stateFalse;
|
||||||
|
|
|
@ -142,7 +142,7 @@ BasicValueFactory::getLazyCompoundValData(const void *store,
|
||||||
}
|
}
|
||||||
|
|
||||||
const llvm::APSInt*
|
const llvm::APSInt*
|
||||||
BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
|
BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
|
||||||
const llvm::APSInt& V1, const llvm::APSInt& V2) {
|
const llvm::APSInt& V1, const llvm::APSInt& V2) {
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace {
|
||||||
class BuiltinFunctionChecker : public Checker {
|
class BuiltinFunctionChecker : public Checker {
|
||||||
public:
|
public:
|
||||||
static void *getTag() { static int tag = 0; return &tag; }
|
static void *getTag() { static int tag = 0; return &tag; }
|
||||||
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
|
virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ void clang::RegisterBuiltinFunctionChecker(GRExprEngine &Eng) {
|
||||||
Eng.registerCheck(new BuiltinFunctionChecker());
|
Eng.registerCheck(new BuiltinFunctionChecker());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinFunctionChecker::EvalCallExpr(CheckerContext &C,const CallExpr *CE){
|
bool BuiltinFunctionChecker::evalCallExpr(CheckerContext &C,const CallExpr *CE){
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
const Expr *Callee = CE->getCallee();
|
const Expr *Callee = CE->getCallee();
|
||||||
SVal L = state->getSVal(Callee);
|
SVal L = state->getSVal(Callee);
|
||||||
|
@ -72,7 +72,7 @@ bool BuiltinFunctionChecker::EvalCallExpr(CheckerContext &C,const CallExpr *CE){
|
||||||
|
|
||||||
SValBuilder& svalBuilder = ValMgr.getSValBuilder();
|
SValBuilder& svalBuilder = ValMgr.getSValBuilder();
|
||||||
DefinedOrUnknownSVal ExtentMatchesSizeArg =
|
DefinedOrUnknownSVal ExtentMatchesSizeArg =
|
||||||
svalBuilder.EvalEQ(state, Extent, Size);
|
svalBuilder.evalEQ(state, Extent, Size);
|
||||||
state = state->Assume(ExtentMatchesSizeArg, true);
|
state = state->Assume(ExtentMatchesSizeArg, true);
|
||||||
|
|
||||||
C.GenerateNode(state->BindExpr(CE, loc::MemRegionVal(R)));
|
C.GenerateNode(state->BindExpr(CE, loc::MemRegionVal(R)));
|
||||||
|
|
|
@ -1710,7 +1710,7 @@ public:
|
||||||
|
|
||||||
// Calls.
|
// Calls.
|
||||||
|
|
||||||
void EvalSummary(ExplodedNodeSet& Dst,
|
void evalSummary(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Eng,
|
GRExprEngine& Eng,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const Expr* Ex,
|
const Expr* Ex,
|
||||||
|
@ -1720,28 +1720,28 @@ public:
|
||||||
ConstExprIterator arg_beg, ConstExprIterator arg_end,
|
ConstExprIterator arg_beg, ConstExprIterator arg_end,
|
||||||
ExplodedNode* Pred, const GRState *state);
|
ExplodedNode* Pred, const GRState *state);
|
||||||
|
|
||||||
virtual void EvalCall(ExplodedNodeSet& Dst,
|
virtual void evalCall(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Eng,
|
GRExprEngine& Eng,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const CallExpr* CE, SVal L,
|
const CallExpr* CE, SVal L,
|
||||||
ExplodedNode* Pred);
|
ExplodedNode* Pred);
|
||||||
|
|
||||||
|
|
||||||
virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
|
virtual void evalObjCMessageExpr(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Engine,
|
GRExprEngine& Engine,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const ObjCMessageExpr* ME,
|
const ObjCMessageExpr* ME,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
const GRState *state);
|
const GRState *state);
|
||||||
// Stores.
|
// Stores.
|
||||||
virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val);
|
virtual void evalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val);
|
||||||
|
|
||||||
// End-of-path.
|
// End-of-path.
|
||||||
|
|
||||||
virtual void EvalEndPath(GRExprEngine& Engine,
|
virtual void evalEndPath(GRExprEngine& Engine,
|
||||||
GREndPathNodeBuilder& Builder);
|
GREndPathNodeBuilder& Builder);
|
||||||
|
|
||||||
virtual void EvalDeadSymbols(ExplodedNodeSet& Dst,
|
virtual void evalDeadSymbols(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Engine,
|
GRExprEngine& Engine,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
|
@ -1754,7 +1754,7 @@ public:
|
||||||
SymbolRef Sym, RefVal V, bool &stop);
|
SymbolRef Sym, RefVal V, bool &stop);
|
||||||
// Return statements.
|
// Return statements.
|
||||||
|
|
||||||
virtual void EvalReturn(ExplodedNodeSet& Dst,
|
virtual void evalReturn(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Engine,
|
GRExprEngine& Engine,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const ReturnStmt* S,
|
const ReturnStmt* S,
|
||||||
|
@ -1762,7 +1762,7 @@ public:
|
||||||
|
|
||||||
// Assumptions.
|
// Assumptions.
|
||||||
|
|
||||||
virtual const GRState *EvalAssume(const GRState* state, SVal condition,
|
virtual const GRState *evalAssume(const GRState* state, SVal condition,
|
||||||
bool assumption);
|
bool assumption);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2494,7 +2494,7 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
|
||||||
return RetTy;
|
return RetTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
|
void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Eng,
|
GRExprEngine& Eng,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const Expr* Ex,
|
const Expr* Ex,
|
||||||
|
@ -2756,7 +2756,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
|
void CFRefCount::evalCall(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Eng,
|
GRExprEngine& Eng,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const CallExpr* CE, SVal L,
|
const CallExpr* CE, SVal L,
|
||||||
|
@ -2777,11 +2777,11 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Summ);
|
assert(Summ);
|
||||||
EvalSummary(Dst, Eng, Builder, CE, 0, *Summ, L.getAsRegion(),
|
evalSummary(Dst, Eng, Builder, CE, 0, *Summ, L.getAsRegion(),
|
||||||
CE->arg_begin(), CE->arg_end(), Pred, Builder.GetState(Pred));
|
CE->arg_begin(), CE->arg_end(), Pred, Builder.GetState(Pred));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst,
|
void CFRefCount::evalObjCMessageExpr(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Eng,
|
GRExprEngine& Eng,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const ObjCMessageExpr* ME,
|
const ObjCMessageExpr* ME,
|
||||||
|
@ -2793,7 +2793,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst,
|
||||||
: Summaries.getClassMethodSummary(ME);
|
: Summaries.getClassMethodSummary(ME);
|
||||||
|
|
||||||
assert(Summ && "RetainSummary is null");
|
assert(Summ && "RetainSummary is null");
|
||||||
EvalSummary(Dst, Eng, Builder, ME,
|
evalSummary(Dst, Eng, Builder, ME,
|
||||||
InstanceReceiver(ME, Pred->getLocationContext()), *Summ, NULL,
|
InstanceReceiver(ME, Pred->getLocationContext()), *Summ, NULL,
|
||||||
ME->arg_begin(), ME->arg_end(), Pred, state);
|
ME->arg_begin(), ME->arg_end(), Pred, state);
|
||||||
}
|
}
|
||||||
|
@ -2813,7 +2813,7 @@ public:
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
|
void CFRefCount::evalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
|
||||||
// Are we storing to something that causes the value to "escape"?
|
// Are we storing to something that causes the value to "escape"?
|
||||||
bool escapes = false;
|
bool escapes = false;
|
||||||
|
|
||||||
|
@ -2852,7 +2852,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
|
||||||
|
|
||||||
// Return statements.
|
// Return statements.
|
||||||
|
|
||||||
void CFRefCount::EvalReturn(ExplodedNodeSet& Dst,
|
void CFRefCount::evalReturn(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Eng,
|
GRExprEngine& Eng,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
const ReturnStmt* S,
|
const ReturnStmt* S,
|
||||||
|
@ -2994,14 +2994,14 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst,
|
||||||
|
|
||||||
// Assumptions.
|
// Assumptions.
|
||||||
|
|
||||||
const GRState* CFRefCount::EvalAssume(const GRState *state,
|
const GRState* CFRefCount::evalAssume(const GRState *state,
|
||||||
SVal Cond, bool Assumption) {
|
SVal Cond, bool Assumption) {
|
||||||
|
|
||||||
// FIXME: We may add to the interface of EvalAssume the list of symbols
|
// FIXME: We may add to the interface of evalAssume the list of symbols
|
||||||
// whose assumptions have changed. For now we just iterate through the
|
// whose assumptions have changed. For now we just iterate through the
|
||||||
// bindings and check if any of the tracked symbols are NULL. This isn't
|
// bindings and check if any of the tracked symbols are NULL. This isn't
|
||||||
// too bad since the number of symbols we will track in practice are
|
// too bad since the number of symbols we will track in practice are
|
||||||
// probably small and EvalAssume is only called at branches and a few
|
// probably small and evalAssume is only called at branches and a few
|
||||||
// other places.
|
// other places.
|
||||||
RefBindings B = state->get<RefBindings>();
|
RefBindings B = state->get<RefBindings>();
|
||||||
|
|
||||||
|
@ -3270,7 +3270,7 @@ CFRefCount::ProcessLeaks(const GRState * state,
|
||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFRefCount::EvalEndPath(GRExprEngine& Eng,
|
void CFRefCount::evalEndPath(GRExprEngine& Eng,
|
||||||
GREndPathNodeBuilder& Builder) {
|
GREndPathNodeBuilder& Builder) {
|
||||||
|
|
||||||
const GRState *state = Builder.getState();
|
const GRState *state = Builder.getState();
|
||||||
|
@ -3297,7 +3297,7 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
|
||||||
ProcessLeaks(state, Leaked, Bd, Eng, Pred);
|
ProcessLeaks(state, Leaked, Bd, Eng, Pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst,
|
void CFRefCount::evalDeadSymbols(ExplodedNodeSet& Dst,
|
||||||
GRExprEngine& Eng,
|
GRExprEngine& Eng,
|
||||||
GRStmtNodeBuilder& Builder,
|
GRStmtNodeBuilder& Builder,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
|
|
|
@ -29,10 +29,10 @@ public:
|
||||||
{}
|
{}
|
||||||
static void *getTag() { static int tag; return &tag; }
|
static void *getTag() { static int tag; return &tag; }
|
||||||
|
|
||||||
bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
|
bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
|
void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
|
||||||
void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
|
void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
|
||||||
void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
|
void evalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
|
||||||
bool WantsRegionChangeUpdate(const GRState *state);
|
bool WantsRegionChangeUpdate(const GRState *state);
|
||||||
|
|
||||||
const GRState *EvalRegionChanges(const GRState *state,
|
const GRState *EvalRegionChanges(const GRState *state,
|
||||||
|
@ -42,20 +42,20 @@ public:
|
||||||
|
|
||||||
typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
|
typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
|
||||||
|
|
||||||
void EvalMemcpy(CheckerContext &C, const CallExpr *CE);
|
void evalMemcpy(CheckerContext &C, const CallExpr *CE);
|
||||||
void EvalMemmove(CheckerContext &C, const CallExpr *CE);
|
void evalMemmove(CheckerContext &C, const CallExpr *CE);
|
||||||
void EvalBcopy(CheckerContext &C, const CallExpr *CE);
|
void evalBcopy(CheckerContext &C, const CallExpr *CE);
|
||||||
void EvalCopyCommon(CheckerContext &C, const GRState *state,
|
void evalCopyCommon(CheckerContext &C, const GRState *state,
|
||||||
const Expr *Size, const Expr *Source, const Expr *Dest,
|
const Expr *Size, const Expr *Source, const Expr *Dest,
|
||||||
bool Restricted = false);
|
bool Restricted = false);
|
||||||
|
|
||||||
void EvalMemcmp(CheckerContext &C, const CallExpr *CE);
|
void evalMemcmp(CheckerContext &C, const CallExpr *CE);
|
||||||
|
|
||||||
void EvalStrlen(CheckerContext &C, const CallExpr *CE);
|
void evalStrlen(CheckerContext &C, const CallExpr *CE);
|
||||||
|
|
||||||
void EvalStrcpy(CheckerContext &C, const CallExpr *CE);
|
void evalStrcpy(CheckerContext &C, const CallExpr *CE);
|
||||||
void EvalStpcpy(CheckerContext &C, const CallExpr *CE);
|
void evalStpcpy(CheckerContext &C, const CallExpr *CE);
|
||||||
void EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool ReturnEnd);
|
void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool ReturnEnd);
|
||||||
|
|
||||||
// Utility methods
|
// Utility methods
|
||||||
std::pair<const GRState*, const GRState*>
|
std::pair<const GRState*, const GRState*>
|
||||||
|
@ -125,7 +125,7 @@ CStringChecker::AssumeZero(CheckerContext &C, const GRState *state, SVal V,
|
||||||
SValBuilder &SV = ValMgr.getSValBuilder();
|
SValBuilder &SV = ValMgr.getSValBuilder();
|
||||||
|
|
||||||
DefinedOrUnknownSVal Zero = ValMgr.makeZeroVal(Ty);
|
DefinedOrUnknownSVal Zero = ValMgr.makeZeroVal(Ty);
|
||||||
DefinedOrUnknownSVal ValIsZero = SV.EvalEQ(state, *Val, Zero);
|
DefinedOrUnknownSVal ValIsZero = SV.evalEQ(state, *Val, Zero);
|
||||||
|
|
||||||
return state->Assume(ValIsZero);
|
return state->Assume(ValIsZero);
|
||||||
}
|
}
|
||||||
|
@ -265,13 +265,13 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
|
||||||
|
|
||||||
// Compute the offset of the last element to be accessed: size-1.
|
// Compute the offset of the last element to be accessed: size-1.
|
||||||
NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
|
NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
|
||||||
NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BO_Sub,
|
NonLoc LastOffset = cast<NonLoc>(SV.evalBinOpNN(state, BO_Sub,
|
||||||
*Length, One, SizeTy));
|
*Length, One, SizeTy));
|
||||||
|
|
||||||
// Check that the first buffer is sufficently long.
|
// Check that the first buffer is sufficently long.
|
||||||
SVal BufStart = SV.EvalCast(BufVal, PtrTy, FirstBuf->getType());
|
SVal BufStart = SV.evalCast(BufVal, PtrTy, FirstBuf->getType());
|
||||||
if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
|
if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
|
||||||
SVal BufEnd = SV.EvalBinOpLN(state, BO_Add, *BufLoc,
|
SVal BufEnd = SV.evalBinOpLN(state, BO_Add, *BufLoc,
|
||||||
LastOffset, PtrTy);
|
LastOffset, PtrTy);
|
||||||
state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination);
|
state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination);
|
||||||
|
|
||||||
|
@ -287,9 +287,9 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
|
||||||
if (!state)
|
if (!state)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
BufStart = SV.EvalCast(BufVal, PtrTy, SecondBuf->getType());
|
BufStart = SV.evalCast(BufVal, PtrTy, SecondBuf->getType());
|
||||||
if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
|
if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
|
||||||
SVal BufEnd = SV.EvalBinOpLN(state, BO_Add, *BufLoc,
|
SVal BufEnd = SV.evalBinOpLN(state, BO_Add, *BufLoc,
|
||||||
LastOffset, PtrTy);
|
LastOffset, PtrTy);
|
||||||
state = CheckLocation(C, state, SecondBuf, BufEnd);
|
state = CheckLocation(C, state, SecondBuf, BufEnd);
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
|
||||||
return state;
|
return state;
|
||||||
|
|
||||||
// Are the two values the same?
|
// Are the two values the same?
|
||||||
DefinedOrUnknownSVal EqualTest = SV.EvalEQ(state, *FirstLoc, *SecondLoc);
|
DefinedOrUnknownSVal EqualTest = SV.evalEQ(state, *FirstLoc, *SecondLoc);
|
||||||
llvm::tie(stateTrue, stateFalse) = state->Assume(EqualTest);
|
llvm::tie(stateTrue, stateFalse) = state->Assume(EqualTest);
|
||||||
|
|
||||||
if (stateTrue && !stateFalse) {
|
if (stateTrue && !stateFalse) {
|
||||||
|
@ -345,7 +345,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
|
||||||
|
|
||||||
// Which value comes first?
|
// Which value comes first?
|
||||||
QualType CmpTy = Ctx.IntTy;
|
QualType CmpTy = Ctx.IntTy;
|
||||||
SVal Reverse = SV.EvalBinOpLL(state, BO_GT,
|
SVal Reverse = SV.evalBinOpLL(state, BO_GT,
|
||||||
*FirstLoc, *SecondLoc, CmpTy);
|
*FirstLoc, *SecondLoc, CmpTy);
|
||||||
DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
|
DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
|
||||||
if (!ReverseTest)
|
if (!ReverseTest)
|
||||||
|
@ -379,20 +379,20 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
|
||||||
// Convert the first buffer's start address to char*.
|
// Convert the first buffer's start address to char*.
|
||||||
// Bail out if the cast fails.
|
// Bail out if the cast fails.
|
||||||
QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
|
QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
|
||||||
SVal FirstStart = SV.EvalCast(*FirstLoc, CharPtrTy, First->getType());
|
SVal FirstStart = SV.evalCast(*FirstLoc, CharPtrTy, First->getType());
|
||||||
Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
|
Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
|
||||||
if (!FirstStartLoc)
|
if (!FirstStartLoc)
|
||||||
return state;
|
return state;
|
||||||
|
|
||||||
// Compute the end of the first buffer. Bail out if THAT fails.
|
// Compute the end of the first buffer. Bail out if THAT fails.
|
||||||
SVal FirstEnd = SV.EvalBinOpLN(state, BO_Add,
|
SVal FirstEnd = SV.evalBinOpLN(state, BO_Add,
|
||||||
*FirstStartLoc, *Length, CharPtrTy);
|
*FirstStartLoc, *Length, CharPtrTy);
|
||||||
Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
|
Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
|
||||||
if (!FirstEndLoc)
|
if (!FirstEndLoc)
|
||||||
return state;
|
return state;
|
||||||
|
|
||||||
// Is the end of the first buffer past the start of the second buffer?
|
// Is the end of the first buffer past the start of the second buffer?
|
||||||
SVal Overlap = SV.EvalBinOpLL(state, BO_GT,
|
SVal Overlap = SV.evalBinOpLL(state, BO_GT,
|
||||||
*FirstEndLoc, *SecondLoc, CmpTy);
|
*FirstEndLoc, *SecondLoc, CmpTy);
|
||||||
DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
|
DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
|
||||||
if (!OverlapTest)
|
if (!OverlapTest)
|
||||||
|
@ -647,10 +647,10 @@ bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Evaluation of individual function calls.
|
// evaluation of individual function calls.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state,
|
void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state,
|
||||||
const Expr *Size, const Expr *Dest,
|
const Expr *Size, const Expr *Dest,
|
||||||
const Expr *Source, bool Restricted) {
|
const Expr *Source, bool Restricted) {
|
||||||
// See if the size argument is zero.
|
// See if the size argument is zero.
|
||||||
|
@ -685,30 +685,30 @@ void CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CStringChecker::EvalMemcpy(CheckerContext &C, const CallExpr *CE) {
|
void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) {
|
||||||
// void *memcpy(void *restrict dst, const void *restrict src, size_t n);
|
// void *memcpy(void *restrict dst, const void *restrict src, size_t n);
|
||||||
// The return value is the address of the destination buffer.
|
// The return value is the address of the destination buffer.
|
||||||
const Expr *Dest = CE->getArg(0);
|
const Expr *Dest = CE->getArg(0);
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
state = state->BindExpr(CE, state->getSVal(Dest));
|
state = state->BindExpr(CE, state->getSVal(Dest));
|
||||||
EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
|
evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalMemmove(CheckerContext &C, const CallExpr *CE) {
|
void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) {
|
||||||
// void *memmove(void *dst, const void *src, size_t n);
|
// void *memmove(void *dst, const void *src, size_t n);
|
||||||
// The return value is the address of the destination buffer.
|
// The return value is the address of the destination buffer.
|
||||||
const Expr *Dest = CE->getArg(0);
|
const Expr *Dest = CE->getArg(0);
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
state = state->BindExpr(CE, state->getSVal(Dest));
|
state = state->BindExpr(CE, state->getSVal(Dest));
|
||||||
EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
|
evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalBcopy(CheckerContext &C, const CallExpr *CE) {
|
void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) {
|
||||||
// void bcopy(const void *src, void *dst, size_t n);
|
// void bcopy(const void *src, void *dst, size_t n);
|
||||||
EvalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
|
evalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
|
void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) {
|
||||||
// int memcmp(const void *s1, const void *s2, size_t n);
|
// int memcmp(const void *s1, const void *s2, size_t n);
|
||||||
const Expr *Left = CE->getArg(0);
|
const Expr *Left = CE->getArg(0);
|
||||||
const Expr *Right = CE->getArg(1);
|
const Expr *Right = CE->getArg(1);
|
||||||
|
@ -744,7 +744,7 @@ void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
|
||||||
DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
|
DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
|
||||||
|
|
||||||
// See if they are the same.
|
// See if they are the same.
|
||||||
DefinedOrUnknownSVal SameBuf = SV.EvalEQ(state, LV, RV);
|
DefinedOrUnknownSVal SameBuf = SV.evalEQ(state, LV, RV);
|
||||||
const GRState *StSameBuf, *StNotSameBuf;
|
const GRState *StSameBuf, *StNotSameBuf;
|
||||||
llvm::tie(StSameBuf, StNotSameBuf) = state->Assume(SameBuf);
|
llvm::tie(StSameBuf, StNotSameBuf) = state->Assume(SameBuf);
|
||||||
|
|
||||||
|
@ -775,7 +775,7 @@ void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalStrlen(CheckerContext &C, const CallExpr *CE) {
|
void CStringChecker::evalStrlen(CheckerContext &C, const CallExpr *CE) {
|
||||||
// size_t strlen(const char *s);
|
// size_t strlen(const char *s);
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
const Expr *Arg = CE->getArg(0);
|
const Expr *Arg = CE->getArg(0);
|
||||||
|
@ -806,17 +806,17 @@ void CStringChecker::EvalStrlen(CheckerContext &C, const CallExpr *CE) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalStrcpy(CheckerContext &C, const CallExpr *CE) {
|
void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) {
|
||||||
// char *strcpy(char *restrict dst, const char *restrict src);
|
// char *strcpy(char *restrict dst, const char *restrict src);
|
||||||
EvalStrcpyCommon(C, CE, /* ReturnEnd = */ false);
|
evalStrcpyCommon(C, CE, /* ReturnEnd = */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalStpcpy(CheckerContext &C, const CallExpr *CE) {
|
void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) {
|
||||||
// char *stpcpy(char *restrict dst, const char *restrict src);
|
// char *stpcpy(char *restrict dst, const char *restrict src);
|
||||||
EvalStrcpyCommon(C, CE, /* ReturnEnd = */ true);
|
evalStrcpyCommon(C, CE, /* ReturnEnd = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
||||||
bool ReturnEnd) {
|
bool ReturnEnd) {
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
|
|
||||||
|
@ -852,7 +852,7 @@ void CStringChecker::EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
||||||
if (NonLoc *KnownStrLen = dyn_cast<NonLoc>(&StrLen)) {
|
if (NonLoc *KnownStrLen = dyn_cast<NonLoc>(&StrLen)) {
|
||||||
SValBuilder &SV = C.getSValBuilder();
|
SValBuilder &SV = C.getSValBuilder();
|
||||||
|
|
||||||
SVal LastElement = SV.EvalBinOpLN(state, BO_Add,
|
SVal LastElement = SV.evalBinOpLN(state, BO_Add,
|
||||||
*DstRegVal, *KnownStrLen,
|
*DstRegVal, *KnownStrLen,
|
||||||
Dst->getType());
|
Dst->getType());
|
||||||
|
|
||||||
|
@ -894,7 +894,7 @@ void CStringChecker::EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
||||||
// The driver method, and other Checker callbacks.
|
// The driver method, and other Checker callbacks.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||||
// Get the callee. All the functions we care about are C functions
|
// Get the callee. All the functions we care about are C functions
|
||||||
// with simple identifiers.
|
// with simple identifiers.
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
|
@ -912,22 +912,22 @@ bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||||
if (Name.startswith("__builtin_"))
|
if (Name.startswith("__builtin_"))
|
||||||
Name = Name.substr(10);
|
Name = Name.substr(10);
|
||||||
|
|
||||||
FnCheck EvalFunction = llvm::StringSwitch<FnCheck>(Name)
|
FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
|
||||||
.Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy)
|
.Cases("memcpy", "__memcpy_chk", &CStringChecker::evalMemcpy)
|
||||||
.Cases("memcmp", "bcmp", &CStringChecker::EvalMemcmp)
|
.Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp)
|
||||||
.Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove)
|
.Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove)
|
||||||
.Cases("strcpy", "__strcpy_chk", &CStringChecker::EvalStrcpy)
|
.Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy)
|
||||||
.Cases("stpcpy", "__stpcpy_chk", &CStringChecker::EvalStpcpy)
|
.Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy)
|
||||||
.Case("strlen", &CStringChecker::EvalStrlen)
|
.Case("strlen", &CStringChecker::evalStrlen)
|
||||||
.Case("bcopy", &CStringChecker::EvalBcopy)
|
.Case("bcopy", &CStringChecker::evalBcopy)
|
||||||
.Default(NULL);
|
.Default(NULL);
|
||||||
|
|
||||||
// If the callee isn't a string function, let another checker handle it.
|
// If the callee isn't a string function, let another checker handle it.
|
||||||
if (!EvalFunction)
|
if (!evalFunction)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check and evaluate the call.
|
// Check and evaluate the call.
|
||||||
(this->*EvalFunction)(C, CE);
|
(this->*evalFunction)(C, CE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,7 +1034,7 @@ void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStringChecker::EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
|
void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
|
||||||
if (!SR.hasDeadSymbols())
|
if (!SR.hasDeadSymbols())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
|
|
||||||
void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
|
void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
|
void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
|
||||||
bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME);
|
bool evalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool PreVisitProcessArg(CheckerContext &C, const Expr *Ex,
|
bool PreVisitProcessArg(CheckerContext &C, const Expr *Ex,
|
||||||
|
@ -244,7 +244,7 @@ void CallAndMessageChecker::PreVisitObjCMessageExpr(CheckerContext &C,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallAndMessageChecker::EvalNilReceiver(CheckerContext &C,
|
bool CallAndMessageChecker::evalNilReceiver(CheckerContext &C,
|
||||||
const ObjCMessageExpr *ME) {
|
const ObjCMessageExpr *ME) {
|
||||||
HandleNilReceiver(C, C.getState(), ME);
|
HandleNilReceiver(C, C.getState(), ME);
|
||||||
return true; // Nil receiver is not handled elsewhere.
|
return true; // Nil receiver is not handled elsewhere.
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
return &x;
|
return &x;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
|
virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
virtual void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
|
virtual void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -62,7 +62,7 @@ void clang::RegisterChrootChecker(GRExprEngine &Eng) {
|
||||||
Eng.registerCheck(new ChrootChecker());
|
Eng.registerCheck(new ChrootChecker());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChrootChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
const Expr *Callee = CE->getCallee();
|
const Expr *Callee = CE->getCallee();
|
||||||
SVal L = state->getSVal(Callee);
|
SVal L = state->getSVal(Callee);
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRExprEngine::EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
|
void GRExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
|
||||||
const FunctionProtoType *FnType,
|
const FunctionProtoType *FnType,
|
||||||
ExplodedNode *Pred, ExplodedNodeSet &Dst,
|
ExplodedNode *Pred, ExplodedNodeSet &Dst,
|
||||||
bool FstArgAsLValue) {
|
bool FstArgAsLValue) {
|
||||||
|
@ -125,9 +125,9 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||||
|
|
||||||
|
|
||||||
// Evaluate other arguments.
|
// Evaluate other arguments.
|
||||||
ExplodedNodeSet ArgsEvaluated;
|
ExplodedNodeSet argsEvaluated;
|
||||||
const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
|
const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
|
||||||
EvalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, ArgsEvaluated);
|
evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
|
||||||
// The callee stack frame context used to create the 'this' parameter region.
|
// The callee stack frame context used to create the 'this' parameter region.
|
||||||
const StackFrameContext *SFC = AMgr.getStackFrame(CD,
|
const StackFrameContext *SFC = AMgr.getStackFrame(CD,
|
||||||
Pred->getLocationContext(),
|
Pred->getLocationContext(),
|
||||||
|
@ -137,8 +137,8 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||||
SFC);
|
SFC);
|
||||||
|
|
||||||
CallEnter Loc(E, SFC, Pred->getLocationContext());
|
CallEnter Loc(E, SFC, Pred->getLocationContext());
|
||||||
for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
|
for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
|
||||||
NE = ArgsEvaluated.end(); NI != NE; ++NI) {
|
NE = argsEvaluated.end(); NI != NE; ++NI) {
|
||||||
const GRState *state = GetState(*NI);
|
const GRState *state = GetState(*NI);
|
||||||
// Setup 'this' region, so that the ctor is evaluated on the object pointed
|
// Setup 'this' region, so that the ctor is evaluated on the object pointed
|
||||||
// by 'Dest'.
|
// by 'Dest'.
|
||||||
|
@ -182,27 +182,27 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
|
||||||
assert(FnType && "Method type not available");
|
assert(FnType && "Method type not available");
|
||||||
|
|
||||||
// Evaluate explicit arguments with a worklist.
|
// Evaluate explicit arguments with a worklist.
|
||||||
ExplodedNodeSet ArgsEvaluated;
|
ExplodedNodeSet argsEvaluated;
|
||||||
EvalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, ArgsEvaluated);
|
evalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, argsEvaluated);
|
||||||
|
|
||||||
// Evaluate the implicit object argument.
|
// Evaluate the implicit object argument.
|
||||||
ExplodedNodeSet AllArgsEvaluated;
|
ExplodedNodeSet AllargsEvaluated;
|
||||||
const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
|
const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
|
||||||
if (!ME)
|
if (!ME)
|
||||||
return;
|
return;
|
||||||
Expr *ObjArgExpr = ME->getBase();
|
Expr *ObjArgExpr = ME->getBase();
|
||||||
for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
|
for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
|
||||||
E = ArgsEvaluated.end(); I != E; ++I) {
|
E = argsEvaluated.end(); I != E; ++I) {
|
||||||
if (ME->isArrow())
|
if (ME->isArrow())
|
||||||
Visit(ObjArgExpr, *I, AllArgsEvaluated);
|
Visit(ObjArgExpr, *I, AllargsEvaluated);
|
||||||
else
|
else
|
||||||
VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
|
VisitLValue(ObjArgExpr, *I, AllargsEvaluated);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now evaluate the call itself.
|
// Now evaluate the call itself.
|
||||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
|
||||||
assert(MD && "not a CXXMethodDecl?");
|
assert(MD && "not a CXXMethodDecl?");
|
||||||
EvalMethodCall(MCE, MD, ObjArgExpr, Pred, AllArgsEvaluated, Dst);
|
evalMethodCall(MCE, MD, ObjArgExpr, Pred, AllargsEvaluated, Dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
|
void GRExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
|
||||||
|
@ -223,14 +223,14 @@ void GRExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
|
||||||
|
|
||||||
// Evaluate arguments treating the first one (object method is called on)
|
// Evaluate arguments treating the first one (object method is called on)
|
||||||
// as alvalue.
|
// as alvalue.
|
||||||
ExplodedNodeSet ArgsEvaluated;
|
ExplodedNodeSet argsEvaluated;
|
||||||
EvalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, ArgsEvaluated, true);
|
evalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, argsEvaluated, true);
|
||||||
|
|
||||||
// Now evaluate the call itself.
|
// Now evaluate the call itself.
|
||||||
EvalMethodCall(C, MD, C->getArg(0), Pred, ArgsEvaluated, Dst);
|
evalMethodCall(C, MD, C->getArg(0), Pred, argsEvaluated, Dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRExprEngine::EvalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
|
void GRExprEngine::evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
|
||||||
const Expr *ThisExpr, ExplodedNode *Pred,
|
const Expr *ThisExpr, ExplodedNode *Pred,
|
||||||
ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
|
ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
|
||||||
// Allow checkers to pre-visit the member call.
|
// Allow checkers to pre-visit the member call.
|
||||||
|
@ -281,13 +281,13 @@ void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
|
||||||
const CXXConstructorDecl *CD = CNE->getConstructor();
|
const CXXConstructorDecl *CD = CNE->getConstructor();
|
||||||
if (CD)
|
if (CD)
|
||||||
FnType = CD->getType()->getAs<FunctionProtoType>();
|
FnType = CD->getType()->getAs<FunctionProtoType>();
|
||||||
ExplodedNodeSet ArgsEvaluated;
|
ExplodedNodeSet argsEvaluated;
|
||||||
EvalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
|
evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
|
||||||
FnType, Pred, ArgsEvaluated);
|
FnType, Pred, argsEvaluated);
|
||||||
|
|
||||||
// Initialize the object region and bind the 'new' expression.
|
// Initialize the object region and bind the 'new' expression.
|
||||||
for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
|
for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
|
||||||
E = ArgsEvaluated.end(); I != E; ++I) {
|
E = argsEvaluated.end(); I != E; ++I) {
|
||||||
const GRState *state = GetState(*I);
|
const GRState *state = GetState(*I);
|
||||||
|
|
||||||
if (ObjTy->isRecordType()) {
|
if (ObjTy->isRecordType()) {
|
||||||
|
@ -310,10 +310,10 @@ void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
|
||||||
void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
|
void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
|
||||||
ExplodedNode *Pred,ExplodedNodeSet &Dst) {
|
ExplodedNode *Pred,ExplodedNodeSet &Dst) {
|
||||||
// Should do more checking.
|
// Should do more checking.
|
||||||
ExplodedNodeSet ArgEvaluated;
|
ExplodedNodeSet Argevaluated;
|
||||||
Visit(CDE->getArgument(), Pred, ArgEvaluated);
|
Visit(CDE->getArgument(), Pred, Argevaluated);
|
||||||
for (ExplodedNodeSet::iterator I = ArgEvaluated.begin(),
|
for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
|
||||||
E = ArgEvaluated.end(); I != E; ++I) {
|
E = Argevaluated.end(); I != E; ++I) {
|
||||||
const GRState *state = GetState(*I);
|
const GRState *state = GetState(*I);
|
||||||
MakeNode(Dst, CDE, *I, state);
|
MakeNode(Dst, CDE, *I, state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,23 +186,23 @@ void GRExprEngine::CheckerEvalNilReceiver(const ObjCMessageExpr *ME,
|
||||||
ExplodedNodeSet &Dst,
|
ExplodedNodeSet &Dst,
|
||||||
const GRState *state,
|
const GRState *state,
|
||||||
ExplodedNode *Pred) {
|
ExplodedNode *Pred) {
|
||||||
bool Evaluated = false;
|
bool evaluated = false;
|
||||||
ExplodedNodeSet DstTmp;
|
ExplodedNodeSet DstTmp;
|
||||||
|
|
||||||
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
|
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
|
||||||
void *tag = I->first;
|
void *tag = I->first;
|
||||||
Checker *checker = I->second;
|
Checker *checker = I->second;
|
||||||
|
|
||||||
if (checker->GR_EvalNilReceiver(DstTmp, *Builder, *this, ME, Pred, state,
|
if (checker->GR_evalNilReceiver(DstTmp, *Builder, *this, ME, Pred, state,
|
||||||
tag)) {
|
tag)) {
|
||||||
Evaluated = true;
|
evaluated = true;
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
// The checker didn't evaluate the expr. Restore the Dst.
|
// The checker didn't evaluate the expr. Restore the Dst.
|
||||||
DstTmp.clear();
|
DstTmp.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Evaluated)
|
if (evaluated)
|
||||||
Dst.insert(DstTmp);
|
Dst.insert(DstTmp);
|
||||||
else
|
else
|
||||||
Dst.insert(Pred);
|
Dst.insert(Pred);
|
||||||
|
@ -214,27 +214,27 @@ void GRExprEngine::CheckerEvalNilReceiver(const ObjCMessageExpr *ME,
|
||||||
bool GRExprEngine::CheckerEvalCall(const CallExpr *CE,
|
bool GRExprEngine::CheckerEvalCall(const CallExpr *CE,
|
||||||
ExplodedNodeSet &Dst,
|
ExplodedNodeSet &Dst,
|
||||||
ExplodedNode *Pred) {
|
ExplodedNode *Pred) {
|
||||||
bool Evaluated = false;
|
bool evaluated = false;
|
||||||
ExplodedNodeSet DstTmp;
|
ExplodedNodeSet DstTmp;
|
||||||
|
|
||||||
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
|
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
|
||||||
void *tag = I->first;
|
void *tag = I->first;
|
||||||
Checker *checker = I->second;
|
Checker *checker = I->second;
|
||||||
|
|
||||||
if (checker->GR_EvalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) {
|
if (checker->GR_evalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) {
|
||||||
Evaluated = true;
|
evaluated = true;
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
// The checker didn't evaluate the expr. Restore the DstTmp set.
|
// The checker didn't evaluate the expr. Restore the DstTmp set.
|
||||||
DstTmp.clear();
|
DstTmp.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Evaluated)
|
if (evaluated)
|
||||||
Dst.insert(DstTmp);
|
Dst.insert(DstTmp);
|
||||||
else
|
else
|
||||||
Dst.insert(Pred);
|
Dst.insert(Pred);
|
||||||
|
|
||||||
return Evaluated;
|
return evaluated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This is largely copy-paste from CheckerVisit(). Need to
|
// FIXME: This is largely copy-paste from CheckerVisit(). Need to
|
||||||
|
@ -382,7 +382,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
SVal V = state->getSVal(loc::MemRegionVal(R));
|
SVal V = state->getSVal(loc::MemRegionVal(R));
|
||||||
SVal Constraint_untested = EvalBinOp(state, BO_GT, V,
|
SVal Constraint_untested = evalBinOp(state, BO_GT, V,
|
||||||
ValMgr.makeZeroVal(T),
|
ValMgr.makeZeroVal(T),
|
||||||
getContext().IntTy);
|
getContext().IntTy);
|
||||||
|
|
||||||
|
@ -420,7 +420,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
|
||||||
// Top-level transfer function logic (Dispatcher).
|
// Top-level transfer function logic (Dispatcher).
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// EvalAssume - Called by ConstraintManager. Used to call checker-specific
|
/// evalAssume - Called by ConstraintManager. Used to call checker-specific
|
||||||
/// logic for handling assumptions on symbolic values.
|
/// logic for handling assumptions on symbolic values.
|
||||||
const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
|
const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
|
||||||
bool assumption) {
|
bool assumption) {
|
||||||
|
@ -456,7 +456,7 @@ const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
|
||||||
Checker *C = I->second;
|
Checker *C = I->second;
|
||||||
bool respondsToCallback = true;
|
bool respondsToCallback = true;
|
||||||
|
|
||||||
state = C->EvalAssume(state, cond, assumption, &respondsToCallback);
|
state = C->evalAssume(state, cond, assumption, &respondsToCallback);
|
||||||
|
|
||||||
// Check if we're building the cache of checkers that care about Assumes.
|
// Check if we're building the cache of checkers that care about Assumes.
|
||||||
if (NewCO.get() && respondsToCallback)
|
if (NewCO.get() && respondsToCallback)
|
||||||
|
@ -473,7 +473,7 @@ const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
|
||||||
if (!state)
|
if (!state)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return TF->EvalAssume(state, cond, assumption);
|
return TF->evalAssume(state, cond, assumption);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GRExprEngine::WantsRegionChangeUpdate(const GRState* state) {
|
bool GRExprEngine::WantsRegionChangeUpdate(const GRState* state) {
|
||||||
|
@ -613,7 +613,7 @@ void GRExprEngine::ProcessStmt(const CFGStmt S, GRStmtNodeBuilder& builder) {
|
||||||
|
|
||||||
// FIXME: This should soon be removed.
|
// FIXME: This should soon be removed.
|
||||||
ExplodedNodeSet Tmp2;
|
ExplodedNodeSet Tmp2;
|
||||||
getTF().EvalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
|
getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
|
||||||
CleanedState, SymReaper);
|
CleanedState, SymReaper);
|
||||||
|
|
||||||
if (Checkers.empty())
|
if (Checkers.empty())
|
||||||
|
@ -635,7 +635,7 @@ void GRExprEngine::ProcessStmt(const CFGStmt S, GRStmtNodeBuilder& builder) {
|
||||||
Checker *checker = I->second;
|
Checker *checker = I->second;
|
||||||
for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();
|
for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();
|
||||||
NI != NE; ++NI)
|
NI != NE; ++NI)
|
||||||
checker->GR_EvalDeadSymbols(*DstSet, *Builder, *this, CurrentStmt,
|
checker->GR_evalDeadSymbols(*DstSet, *Builder, *this, CurrentStmt,
|
||||||
*NI, SymReaper, tag);
|
*NI, SymReaper, tag);
|
||||||
SrcSet = DstSet;
|
SrcSet = DstSet;
|
||||||
}
|
}
|
||||||
|
@ -907,7 +907,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
|
||||||
(B->isRelationalOp() || B->isEqualityOp())) {
|
(B->isRelationalOp() || B->isEqualityOp())) {
|
||||||
ExplodedNodeSet Tmp;
|
ExplodedNodeSet Tmp;
|
||||||
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp, false);
|
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp, false);
|
||||||
EvalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
|
evalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
|
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
|
||||||
|
@ -1092,7 +1092,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
|
||||||
if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {
|
if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {
|
||||||
ExplodedNodeSet Tmp;
|
ExplodedNodeSet Tmp;
|
||||||
VisitUnaryOperator(U, Pred, Tmp, false);
|
VisitUnaryOperator(U, Pred, Tmp, false);
|
||||||
EvalEagerlyAssume(Dst, Tmp, U);
|
evalEagerlyAssume(Dst, Tmp, U);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
VisitUnaryOperator(U, Pred, Dst, false);
|
VisitUnaryOperator(U, Pred, Dst, false);
|
||||||
|
@ -1534,12 +1534,12 @@ void GRExprEngine::VisitGuardedExpr(const Expr* Ex, const Expr* L,
|
||||||
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
|
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
|
||||||
/// nodes when the control reaches the end of a function.
|
/// nodes when the control reaches the end of a function.
|
||||||
void GRExprEngine::ProcessEndPath(GREndPathNodeBuilder& builder) {
|
void GRExprEngine::ProcessEndPath(GREndPathNodeBuilder& builder) {
|
||||||
getTF().EvalEndPath(*this, builder);
|
getTF().evalEndPath(*this, builder);
|
||||||
StateMgr.EndPath(builder.getState());
|
StateMgr.EndPath(builder.getState());
|
||||||
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
|
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
|
||||||
void *tag = I->first;
|
void *tag = I->first;
|
||||||
Checker *checker = I->second;
|
Checker *checker = I->second;
|
||||||
checker->EvalEndPath(builder, tag, *this);
|
checker->evalEndPath(builder, tag, *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1597,7 +1597,7 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));
|
nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));
|
||||||
DefinedOrUnknownSVal Res = svalBuilder.EvalEQ(DefaultSt ? DefaultSt : state,
|
DefinedOrUnknownSVal Res = svalBuilder.evalEQ(DefaultSt ? DefaultSt : state,
|
||||||
CondV, CaseVal);
|
CondV, CaseVal);
|
||||||
|
|
||||||
// Now "assume" that the case matches.
|
// Now "assume" that the case matches.
|
||||||
|
@ -1804,7 +1804,7 @@ void GRExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
|
||||||
ProgramPoint::PostLValueKind);
|
ProgramPoint::PostLValueKind);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
EvalLoad(Dst, Ex, Pred, state, V);
|
evalLoad(Dst, Ex, Pred, state, V);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
|
} else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
|
||||||
|
@ -1861,7 +1861,7 @@ void GRExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr* A,
|
||||||
MakeNode(Dst, A, *I2, state->BindExpr(A, V),
|
MakeNode(Dst, A, *I2, state->BindExpr(A, V),
|
||||||
ProgramPoint::PostLValueKind);
|
ProgramPoint::PostLValueKind);
|
||||||
else
|
else
|
||||||
EvalLoad(Dst, A, *I2, state, V);
|
evalLoad(Dst, A, *I2, state, V);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1892,13 +1892,13 @@ void GRExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
|
||||||
if (asLValue)
|
if (asLValue)
|
||||||
MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
|
MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
|
||||||
else
|
else
|
||||||
EvalLoad(Dst, M, *I, state, L);
|
evalLoad(Dst, M, *I, state, L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EvalBind - Handle the semantics of binding a value to a specific location.
|
/// evalBind - Handle the semantics of binding a value to a specific location.
|
||||||
/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
|
/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
|
||||||
void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
|
void GRExprEngine::evalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
|
||||||
ExplodedNode* Pred, const GRState* state,
|
ExplodedNode* Pred, const GRState* state,
|
||||||
SVal location, SVal Val, bool atDeclInit) {
|
SVal location, SVal Val, bool atDeclInit) {
|
||||||
|
|
||||||
|
@ -1946,11 +1946,11 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
|
||||||
GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
|
GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
getTF().EvalBind(BuilderRef, location, Val);
|
getTF().evalBind(BuilderRef, location, Val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EvalStore - Handle the semantics of a store via an assignment.
|
/// evalStore - Handle the semantics of a store via an assignment.
|
||||||
/// @param Dst The node set to store generated state nodes
|
/// @param Dst The node set to store generated state nodes
|
||||||
/// @param AssignE The assignment expression if the store happens in an
|
/// @param AssignE The assignment expression if the store happens in an
|
||||||
/// assignment.
|
/// assignment.
|
||||||
|
@ -1958,7 +1958,7 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
|
||||||
/// @param state The current simulation state
|
/// @param state The current simulation state
|
||||||
/// @param location The location to store the value
|
/// @param location The location to store the value
|
||||||
/// @param Val The value to be stored
|
/// @param Val The value to be stored
|
||||||
void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
|
void GRExprEngine::evalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
|
||||||
const Expr* LocationE,
|
const Expr* LocationE,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
const GRState* state, SVal location, SVal Val,
|
const GRState* state, SVal location, SVal Val,
|
||||||
|
@ -1968,7 +1968,7 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
|
||||||
|
|
||||||
// Evaluate the location (checks for bad dereferences).
|
// Evaluate the location (checks for bad dereferences).
|
||||||
ExplodedNodeSet Tmp;
|
ExplodedNodeSet Tmp;
|
||||||
EvalLocation(Tmp, LocationE, Pred, state, location, tag, false);
|
evalLocation(Tmp, LocationE, Pred, state, location, tag, false);
|
||||||
|
|
||||||
if (Tmp.empty())
|
if (Tmp.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -1984,10 +1984,10 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
|
||||||
const Expr *StoreE = AssignE ? AssignE : LocationE;
|
const Expr *StoreE = AssignE ? AssignE : LocationE;
|
||||||
|
|
||||||
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
|
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
|
||||||
EvalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);
|
evalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, const Expr *Ex,
|
void GRExprEngine::evalLoad(ExplodedNodeSet& Dst, const Expr *Ex,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
const GRState* state, SVal location,
|
const GRState* state, SVal location,
|
||||||
const void *tag, QualType LoadTy) {
|
const void *tag, QualType LoadTy) {
|
||||||
|
@ -2003,30 +2003,30 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, const Expr *Ex,
|
||||||
if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
|
if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
|
||||||
static int loadReferenceTag = 0;
|
static int loadReferenceTag = 0;
|
||||||
ExplodedNodeSet Tmp;
|
ExplodedNodeSet Tmp;
|
||||||
EvalLoadCommon(Tmp, Ex, Pred, state, location, &loadReferenceTag,
|
evalLoadCommon(Tmp, Ex, Pred, state, location, &loadReferenceTag,
|
||||||
getContext().getPointerType(RT->getPointeeType()));
|
getContext().getPointerType(RT->getPointeeType()));
|
||||||
|
|
||||||
// Perform the load from the referenced value.
|
// Perform the load from the referenced value.
|
||||||
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
|
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
|
||||||
state = GetState(*I);
|
state = GetState(*I);
|
||||||
location = state->getSVal(Ex);
|
location = state->getSVal(Ex);
|
||||||
EvalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);
|
evalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);
|
evalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,
|
void GRExprEngine::evalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
const GRState* state, SVal location,
|
const GRState* state, SVal location,
|
||||||
const void *tag, QualType LoadTy) {
|
const void *tag, QualType LoadTy) {
|
||||||
|
|
||||||
// Evaluate the location (checks for bad dereferences).
|
// Evaluate the location (checks for bad dereferences).
|
||||||
ExplodedNodeSet Tmp;
|
ExplodedNodeSet Tmp;
|
||||||
EvalLocation(Tmp, Ex, Pred, state, location, tag, true);
|
evalLocation(Tmp, Ex, Pred, state, location, tag, true);
|
||||||
|
|
||||||
if (Tmp.empty())
|
if (Tmp.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -2055,7 +2055,7 @@ void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, const Stmt *S,
|
void GRExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
|
||||||
ExplodedNode* Pred,
|
ExplodedNode* Pred,
|
||||||
const GRState* state, SVal location,
|
const GRState* state, SVal location,
|
||||||
const void *tag, bool isLoad) {
|
const void *tag, bool isLoad) {
|
||||||
|
@ -2150,7 +2150,7 @@ void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
|
||||||
|
|
||||||
// Evaluate the arguments.
|
// Evaluate the arguments.
|
||||||
ExplodedNodeSet ArgsEvaluated;
|
ExplodedNodeSet ArgsEvaluated;
|
||||||
EvalArguments(CE->arg_begin(), CE->arg_end(), Proto, Pred, ArgsEvaluated);
|
evalArguments(CE->arg_begin(), CE->arg_end(), Proto, Pred, ArgsEvaluated);
|
||||||
|
|
||||||
// Now process the call itself.
|
// Now process the call itself.
|
||||||
ExplodedNodeSet DstTmp;
|
ExplodedNodeSet DstTmp;
|
||||||
|
@ -2193,18 +2193,18 @@ void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
|
||||||
DI_Checker != DE_Checker; ++DI_Checker) {
|
DI_Checker != DE_Checker; ++DI_Checker) {
|
||||||
|
|
||||||
// Dispatch to the plug-in transfer function.
|
// Dispatch to the plug-in transfer function.
|
||||||
unsigned OldSize = DstTmp3.size();
|
unsigned oldSize = DstTmp3.size();
|
||||||
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
||||||
Pred = *DI_Checker;
|
Pred = *DI_Checker;
|
||||||
|
|
||||||
// Dispatch to transfer function logic to handle the call itself.
|
// Dispatch to transfer function logic to handle the call itself.
|
||||||
// FIXME: Allow us to chain together transfer functions.
|
// FIXME: Allow us to chain together transfer functions.
|
||||||
assert(Builder && "GRStmtNodeBuilder must be defined.");
|
assert(Builder && "GRStmtNodeBuilder must be defined.");
|
||||||
getTF().EvalCall(DstTmp3, *this, *Builder, CE, L, Pred);
|
getTF().evalCall(DstTmp3, *this, *Builder, CE, L, Pred);
|
||||||
|
|
||||||
// Handle the case where no nodes where generated. Auto-generate that
|
// Handle the case where no nodes where generated. Auto-generate that
|
||||||
// contains the updated state if we aren't generating sinks.
|
// contains the updated state if we aren't generating sinks.
|
||||||
if (!Builder->BuildSinks && DstTmp3.size() == OldSize &&
|
if (!Builder->BuildSinks && DstTmp3.size() == oldSize &&
|
||||||
!Builder->HasGeneratedNode)
|
!Builder->HasGeneratedNode)
|
||||||
MakeNode(DstTmp3, CE, Pred, state);
|
MakeNode(DstTmp3, CE, Pred, state);
|
||||||
}
|
}
|
||||||
|
@ -2233,7 +2233,7 @@ void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
|
||||||
for (ExplodedNodeSet::iterator NI = DstTmp4.begin(), NE = DstTmp4.end();
|
for (ExplodedNodeSet::iterator NI = DstTmp4.begin(), NE = DstTmp4.end();
|
||||||
NI!=NE; ++NI) {
|
NI!=NE; ++NI) {
|
||||||
const GRState *state = GetState(*NI);
|
const GRState *state = GetState(*NI);
|
||||||
EvalLoad(Dst, CE, *NI, state, state->getSVal(CE),
|
evalLoad(Dst, CE, *NI, state, state->getSVal(CE),
|
||||||
&ConvertToRvalueTag, LoadTy);
|
&ConvertToRvalueTag, LoadTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2245,7 +2245,7 @@ void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
|
||||||
static std::pair<const void*,const void*> EagerlyAssumeTag
|
static std::pair<const void*,const void*> EagerlyAssumeTag
|
||||||
= std::pair<const void*,const void*>(&EagerlyAssumeTag,static_cast<void*>(0));
|
= std::pair<const void*,const void*>(&EagerlyAssumeTag,static_cast<void*>(0));
|
||||||
|
|
||||||
void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
void GRExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
||||||
const Expr *Ex) {
|
const Expr *Ex) {
|
||||||
for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
|
for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
|
||||||
ExplodedNode *Pred = *I;
|
ExplodedNode *Pred = *I;
|
||||||
|
@ -2322,7 +2322,7 @@ void GRExprEngine::VisitObjCIvarRefExpr(const ObjCIvarRefExpr* Ex,
|
||||||
if (asLValue)
|
if (asLValue)
|
||||||
MakeNode(Dst, Ex, *I, state->BindExpr(Ex, location));
|
MakeNode(Dst, Ex, *I, state->BindExpr(Ex, location));
|
||||||
else
|
else
|
||||||
EvalLoad(Dst, Ex, *I, state, location);
|
evalLoad(Dst, Ex, *I, state, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2385,7 +2385,7 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
|
||||||
// Check if the location we are writing back to is a null pointer.
|
// Check if the location we are writing back to is a null pointer.
|
||||||
const Stmt* elem = S->getElement();
|
const Stmt* elem = S->getElement();
|
||||||
ExplodedNodeSet Tmp;
|
ExplodedNodeSet Tmp;
|
||||||
EvalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
|
evalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
|
||||||
|
|
||||||
if (Tmp.empty())
|
if (Tmp.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -2490,14 +2490,14 @@ void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
|
||||||
CheckerVisit(ME, DstPrevisit, ArgsEvaluated, PreVisitStmtCallback);
|
CheckerVisit(ME, DstPrevisit, ArgsEvaluated, PreVisitStmtCallback);
|
||||||
|
|
||||||
// Proceed with evaluate the message expression.
|
// Proceed with evaluate the message expression.
|
||||||
ExplodedNodeSet DstEval;
|
ExplodedNodeSet dstEval;
|
||||||
|
|
||||||
for (ExplodedNodeSet::iterator DI = DstPrevisit.begin(),
|
for (ExplodedNodeSet::iterator DI = DstPrevisit.begin(),
|
||||||
DE = DstPrevisit.end(); DI != DE; ++DI) {
|
DE = DstPrevisit.end(); DI != DE; ++DI) {
|
||||||
|
|
||||||
Pred = *DI;
|
Pred = *DI;
|
||||||
bool RaisesException = false;
|
bool RaisesException = false;
|
||||||
unsigned OldSize = DstEval.size();
|
unsigned oldSize = dstEval.size();
|
||||||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||||
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
||||||
|
|
||||||
|
@ -2514,7 +2514,7 @@ void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
|
||||||
// There are three cases: can be nil or non-nil, must be nil, must be
|
// There are three cases: can be nil or non-nil, must be nil, must be
|
||||||
// non-nil. We handle must be nil, and merge the rest two into non-nil.
|
// non-nil. We handle must be nil, and merge the rest two into non-nil.
|
||||||
if (nilState && !notNilState) {
|
if (nilState && !notNilState) {
|
||||||
CheckerEvalNilReceiver(ME, DstEval, nilState, Pred);
|
CheckerEvalNilReceiver(ME, dstEval, nilState, Pred);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2529,7 +2529,7 @@ void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
|
||||||
Builder->BuildSinks = true;
|
Builder->BuildSinks = true;
|
||||||
|
|
||||||
// Dispatch to plug-in transfer function.
|
// Dispatch to plug-in transfer function.
|
||||||
EvalObjCMessageExpr(DstEval, ME, Pred, notNilState);
|
evalObjCMessageExpr(dstEval, ME, Pred, notNilState);
|
||||||
}
|
}
|
||||||
else if (ObjCInterfaceDecl *Iface = ME->getReceiverInterface()) {
|
else if (ObjCInterfaceDecl *Iface = ME->getReceiverInterface()) {
|
||||||
IdentifierInfo* ClsName = Iface->getIdentifier();
|
IdentifierInfo* ClsName = Iface->getIdentifier();
|
||||||
|
@ -2577,20 +2577,20 @@ void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
|
||||||
Builder->BuildSinks = true;
|
Builder->BuildSinks = true;
|
||||||
|
|
||||||
// Dispatch to plug-in transfer function.
|
// Dispatch to plug-in transfer function.
|
||||||
EvalObjCMessageExpr(DstEval, ME, Pred, Builder->GetState(Pred));
|
evalObjCMessageExpr(dstEval, ME, Pred, Builder->GetState(Pred));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the case where no nodes where generated. Auto-generate that
|
// Handle the case where no nodes where generated. Auto-generate that
|
||||||
// contains the updated state if we aren't generating sinks.
|
// contains the updated state if we aren't generating sinks.
|
||||||
if (!Builder->BuildSinks && DstEval.size() == OldSize &&
|
if (!Builder->BuildSinks && dstEval.size() == oldSize &&
|
||||||
!Builder->HasGeneratedNode)
|
!Builder->HasGeneratedNode)
|
||||||
MakeNode(DstEval, ME, Pred, GetState(Pred));
|
MakeNode(dstEval, ME, Pred, GetState(Pred));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, perform the post-condition check of the ObjCMessageExpr and store
|
// Finally, perform the post-condition check of the ObjCMessageExpr and store
|
||||||
// the created nodes in 'Dst'.
|
// the created nodes in 'Dst'.
|
||||||
if (!(!asLValue && ReceiverReturnsReference(ME))) {
|
if (!(!asLValue && ReceiverReturnsReference(ME))) {
|
||||||
CheckerVisit(ME, Dst, DstEval, PostVisitStmtCallback);
|
CheckerVisit(ME, Dst, dstEval, PostVisitStmtCallback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2600,14 +2600,14 @@ void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
|
||||||
// FIXME: This conversion doesn't actually happen unless the result
|
// FIXME: This conversion doesn't actually happen unless the result
|
||||||
// of ObjCMessageExpr is consumed by another expression.
|
// of ObjCMessageExpr is consumed by another expression.
|
||||||
ExplodedNodeSet DstRValueConvert;
|
ExplodedNodeSet DstRValueConvert;
|
||||||
CheckerVisit(ME, DstRValueConvert, DstEval, PostVisitStmtCallback);
|
CheckerVisit(ME, DstRValueConvert, dstEval, PostVisitStmtCallback);
|
||||||
QualType LoadTy = ME->getType();
|
QualType LoadTy = ME->getType();
|
||||||
|
|
||||||
static int *ConvertToRvalueTag = 0;
|
static int *ConvertToRvalueTag = 0;
|
||||||
for (ExplodedNodeSet::iterator NI = DstRValueConvert.begin(),
|
for (ExplodedNodeSet::iterator NI = DstRValueConvert.begin(),
|
||||||
NE = DstRValueConvert.end(); NI != NE; ++NI) {
|
NE = DstRValueConvert.end(); NI != NE; ++NI) {
|
||||||
const GRState *state = GetState(*NI);
|
const GRState *state = GetState(*NI);
|
||||||
EvalLoad(Dst, ME, *NI, state, state->getSVal(ME),
|
evalLoad(Dst, ME, *NI, state, state->getSVal(ME),
|
||||||
&ConvertToRvalueTag, LoadTy);
|
&ConvertToRvalueTag, LoadTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2696,7 +2696,7 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
||||||
ExplodedNode* N = *I;
|
ExplodedNode* N = *I;
|
||||||
const GRState* state = GetState(N);
|
const GRState* state = GetState(N);
|
||||||
SVal V = state->getSVal(Ex);
|
SVal V = state->getSVal(Ex);
|
||||||
V = svalBuilder.EvalCast(V, T, ExTy);
|
V = svalBuilder.evalCast(V, T, ExTy);
|
||||||
state = state->BindExpr(CastE, V);
|
state = state->BindExpr(CastE, V);
|
||||||
MakeNode(Dst, CastE, N, state);
|
MakeNode(Dst, CastE, N, state);
|
||||||
}
|
}
|
||||||
|
@ -2805,7 +2805,7 @@ void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
|
||||||
Builder->getCurrentBlockCount());
|
Builder->getCurrentBlockCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalBind(Dst, DS, *I, state,
|
evalBind(Dst, DS, *I, state,
|
||||||
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
|
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2837,7 +2837,7 @@ void GRExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S,
|
||||||
Builder->getCurrentBlockCount());
|
Builder->getCurrentBlockCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalBind(Dst, S, N, state,
|
evalBind(Dst, S, N, state,
|
||||||
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
|
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3041,7 +3041,7 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
MakeNode(Dst, U, *I, state->BindExpr(U, location),
|
MakeNode(Dst, U, *I, state->BindExpr(U, location),
|
||||||
ProgramPoint::PostLValueKind);
|
ProgramPoint::PostLValueKind);
|
||||||
else
|
else
|
||||||
EvalLoad(Dst, U, *I, state, location);
|
evalLoad(Dst, U, *I, state, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -3159,7 +3159,7 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
// QualType SrcT = getContext().getCanonicalType(Ex->getType());
|
// QualType SrcT = getContext().getCanonicalType(Ex->getType());
|
||||||
//
|
//
|
||||||
// if (DstT != SrcT) // Perform promotions.
|
// if (DstT != SrcT) // Perform promotions.
|
||||||
// V = EvalCast(V, DstT);
|
// V = evalCast(V, DstT);
|
||||||
//
|
//
|
||||||
// if (V.isUnknownOrUndef()) {
|
// if (V.isUnknownOrUndef()) {
|
||||||
// MakeNode(Dst, U, *I, BindExpr(St, U, V));
|
// MakeNode(Dst, U, *I, BindExpr(St, U, V));
|
||||||
|
@ -3173,12 +3173,12 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
|
|
||||||
case UO_Not:
|
case UO_Not:
|
||||||
// FIXME: Do we need to handle promotions?
|
// FIXME: Do we need to handle promotions?
|
||||||
state = state->BindExpr(U, EvalComplement(cast<NonLoc>(V)));
|
state = state->BindExpr(U, evalComplement(cast<NonLoc>(V)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UO_Minus:
|
case UO_Minus:
|
||||||
// FIXME: Do we need to handle promotions?
|
// FIXME: Do we need to handle promotions?
|
||||||
state = state->BindExpr(U, EvalMinus(cast<NonLoc>(V)));
|
state = state->BindExpr(U, evalMinus(cast<NonLoc>(V)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UO_LNot:
|
case UO_LNot:
|
||||||
|
@ -3191,12 +3191,12 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
|
|
||||||
if (isa<Loc>(V)) {
|
if (isa<Loc>(V)) {
|
||||||
Loc X = ValMgr.makeNull();
|
Loc X = ValMgr.makeNull();
|
||||||
Result = EvalBinOp(state, BO_EQ, cast<Loc>(V), X,
|
Result = evalBinOp(state, BO_EQ, cast<Loc>(V), X,
|
||||||
U->getType());
|
U->getType());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
|
nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
|
||||||
Result = EvalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
|
Result = evalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
|
||||||
U->getType());
|
U->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3226,7 +3226,7 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
|
|
||||||
// Perform a load.
|
// Perform a load.
|
||||||
ExplodedNodeSet Tmp2;
|
ExplodedNodeSet Tmp2;
|
||||||
EvalLoad(Tmp2, Ex, *I, state, V1);
|
evalLoad(Tmp2, Ex, *I, state, V1);
|
||||||
|
|
||||||
for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
|
for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
|
||||||
|
|
||||||
|
@ -3254,7 +3254,7 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
else
|
else
|
||||||
RHS = ValMgr.makeIntVal(1, U->getType());
|
RHS = ValMgr.makeIntVal(1, U->getType());
|
||||||
|
|
||||||
SVal Result = EvalBinOp(state, Op, V2, RHS, U->getType());
|
SVal Result = evalBinOp(state, Op, V2, RHS, U->getType());
|
||||||
|
|
||||||
// Conjure a new symbol if necessary to recover precision.
|
// Conjure a new symbol if necessary to recover precision.
|
||||||
if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
|
if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
|
||||||
|
@ -3268,12 +3268,12 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
// propagate that constraint.
|
// propagate that constraint.
|
||||||
if (Loc::IsLocType(U->getType())) {
|
if (Loc::IsLocType(U->getType())) {
|
||||||
DefinedOrUnknownSVal Constraint =
|
DefinedOrUnknownSVal Constraint =
|
||||||
svalBuilder.EvalEQ(state, V2, ValMgr.makeZeroVal(U->getType()));
|
svalBuilder.evalEQ(state, V2, ValMgr.makeZeroVal(U->getType()));
|
||||||
|
|
||||||
if (!state->Assume(Constraint, true)) {
|
if (!state->Assume(Constraint, true)) {
|
||||||
// It isn't feasible for the original value to be null.
|
// It isn't feasible for the original value to be null.
|
||||||
// Propagate this constraint.
|
// Propagate this constraint.
|
||||||
Constraint = svalBuilder.EvalEQ(state, SymVal,
|
Constraint = svalBuilder.evalEQ(state, SymVal,
|
||||||
ValMgr.makeZeroVal(U->getType()));
|
ValMgr.makeZeroVal(U->getType()));
|
||||||
|
|
||||||
|
|
||||||
|
@ -3286,7 +3286,7 @@ void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
||||||
state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
|
state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
|
||||||
|
|
||||||
// Perform the store.
|
// Perform the store.
|
||||||
EvalStore(Dst, NULL, U, *I2, state, V1, Result);
|
evalStore(Dst, NULL, U, *I2, state, V1, Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3388,7 +3388,7 @@ void GRExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
|
||||||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||||
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
||||||
|
|
||||||
getTF().EvalReturn(Dst, *this, *Builder, RS, Pred);
|
getTF().evalReturn(Dst, *this, *Builder, RS, Pred);
|
||||||
|
|
||||||
// Handle the case where no nodes where generated.
|
// Handle the case where no nodes where generated.
|
||||||
if (!Builder->BuildSinks && Dst.size() == size &&
|
if (!Builder->BuildSinks && Dst.size() == size &&
|
||||||
|
@ -3455,14 +3455,14 @@ void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
|
||||||
|
|
||||||
// Simulate the effects of a "store": bind the value of the RHS
|
// Simulate the effects of a "store": bind the value of the RHS
|
||||||
// to the L-Value represented by the LHS.
|
// to the L-Value represented by the LHS.
|
||||||
EvalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV);
|
evalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!B->isAssignmentOp()) {
|
if (!B->isAssignmentOp()) {
|
||||||
// Process non-assignments except commas or short-circuited
|
// Process non-assignments except commas or short-circuited
|
||||||
// logical expressions (LAnd and LOr).
|
// logical expressions (LAnd and LOr).
|
||||||
SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType());
|
SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
|
||||||
|
|
||||||
if (Result.isUnknown()) {
|
if (Result.isUnknown()) {
|
||||||
MakeNode(Tmp3, B, *I2, state);
|
MakeNode(Tmp3, B, *I2, state);
|
||||||
|
@ -3496,7 +3496,7 @@ void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
|
||||||
// null dereferences, and so on.
|
// null dereferences, and so on.
|
||||||
ExplodedNodeSet Tmp4;
|
ExplodedNodeSet Tmp4;
|
||||||
SVal location = state->getSVal(LHS);
|
SVal location = state->getSVal(LHS);
|
||||||
EvalLoad(Tmp4, LHS, *I2, state, location);
|
evalLoad(Tmp4, LHS, *I2, state, location);
|
||||||
|
|
||||||
for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
|
for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
|
||||||
++I4) {
|
++I4) {
|
||||||
|
@ -3516,10 +3516,10 @@ void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
|
||||||
QualType RTy = getContext().getCanonicalType(RHS->getType());
|
QualType RTy = getContext().getCanonicalType(RHS->getType());
|
||||||
|
|
||||||
// Promote LHS.
|
// Promote LHS.
|
||||||
V = svalBuilder.EvalCast(V, CLHSTy, LTy);
|
V = svalBuilder.evalCast(V, CLHSTy, LTy);
|
||||||
|
|
||||||
// Compute the result of the operation.
|
// Compute the result of the operation.
|
||||||
SVal Result = svalBuilder.EvalCast(EvalBinOp(state, Op, V, RightV, CTy),
|
SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
|
||||||
B->getType(), CTy);
|
B->getType(), CTy);
|
||||||
|
|
||||||
// EXPERIMENTAL: "Conjured" symbols.
|
// EXPERIMENTAL: "Conjured" symbols.
|
||||||
|
@ -3538,15 +3538,15 @@ void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
|
||||||
LHSVal = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count);
|
LHSVal = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count);
|
||||||
|
|
||||||
// However, we need to convert the symbol to the computation type.
|
// However, we need to convert the symbol to the computation type.
|
||||||
Result = svalBuilder.EvalCast(LHSVal, CTy, LTy);
|
Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// The left-hand side may bind to a different value then the
|
// The left-hand side may bind to a different value then the
|
||||||
// computation type.
|
// computation type.
|
||||||
LHSVal = svalBuilder.EvalCast(Result, LTy, CTy);
|
LHSVal = svalBuilder.evalCast(Result, LTy, CTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalStore(Tmp3, B, LHS, *I4, state->BindExpr(B, Result),
|
evalStore(Tmp3, B, LHS, *I4, state->BindExpr(B, Result),
|
||||||
location, LHSVal);
|
location, LHSVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,27 +251,27 @@ const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
|
||||||
nonloc::ConcreteInt Min = BVF.getMinValue(IndexTy);
|
nonloc::ConcreteInt Min = BVF.getMinValue(IndexTy);
|
||||||
|
|
||||||
// Adjust the index.
|
// Adjust the index.
|
||||||
SVal NewIdx = SV.EvalBinOpNN(this, BO_Add,
|
SVal newIdx = SV.evalBinOpNN(this, BO_Add,
|
||||||
cast<NonLoc>(Idx), Min, IndexTy);
|
cast<NonLoc>(Idx), Min, IndexTy);
|
||||||
if (NewIdx.isUnknownOrUndef())
|
if (newIdx.isUnknownOrUndef())
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
// Adjust the upper bound.
|
// Adjust the upper bound.
|
||||||
SVal NewBound = SV.EvalBinOpNN(this, BO_Add,
|
SVal NewBound = SV.evalBinOpNN(this, BO_Add,
|
||||||
cast<NonLoc>(UpperBound), Min, IndexTy);
|
cast<NonLoc>(UpperBound), Min, IndexTy);
|
||||||
if (NewBound.isUnknownOrUndef())
|
if (NewBound.isUnknownOrUndef())
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
// Build the actual comparison.
|
// Build the actual comparison.
|
||||||
SVal InBound = SV.EvalBinOpNN(this, BO_LT,
|
SVal inBound = SV.evalBinOpNN(this, BO_LT,
|
||||||
cast<NonLoc>(NewIdx), cast<NonLoc>(NewBound),
|
cast<NonLoc>(newIdx), cast<NonLoc>(NewBound),
|
||||||
Ctx.IntTy);
|
Ctx.IntTy);
|
||||||
if (InBound.isUnknownOrUndef())
|
if (inBound.isUnknownOrUndef())
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
// Finally, let the constraint manager take care of it.
|
// Finally, let the constraint manager take care of it.
|
||||||
ConstraintManager &CM = SM.getConstraintManager();
|
ConstraintManager &CM = SM.getConstraintManager();
|
||||||
return CM.Assume(this, cast<DefinedSVal>(InBound), Assumption);
|
return CM.Assume(this, cast<DefinedSVal>(inBound), Assumption);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
|
const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
|
||||||
|
|
|
@ -75,11 +75,11 @@ public:
|
||||||
BT_BadFree(0),
|
BT_BadFree(0),
|
||||||
II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
|
II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
|
||||||
static void *getTag();
|
static void *getTag();
|
||||||
bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
|
bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
|
void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
|
||||||
void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
|
void evalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
|
||||||
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
|
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
|
||||||
const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption,
|
const GRState *evalAssume(const GRState *state, SVal Cond, bool Assumption,
|
||||||
bool *respondsToCallback);
|
bool *respondsToCallback);
|
||||||
void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
|
void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
|
||||||
virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
|
virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
|
||||||
|
@ -132,7 +132,7 @@ void *MallocChecker::getTag() {
|
||||||
return &x;
|
return &x;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
bool MallocChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
const Expr *Callee = CE->getCallee();
|
const Expr *Callee = CE->getCallee();
|
||||||
SVal L = state->getSVal(Callee);
|
SVal L = state->getSVal(Callee);
|
||||||
|
@ -243,7 +243,7 @@ const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
|
||||||
|
|
||||||
SValBuilder &svalBuilder = ValMgr.getSValBuilder();
|
SValBuilder &svalBuilder = ValMgr.getSValBuilder();
|
||||||
DefinedOrUnknownSVal ExtentMatchesSize =
|
DefinedOrUnknownSVal ExtentMatchesSize =
|
||||||
svalBuilder.EvalEQ(state, Extent, DefinedSize);
|
svalBuilder.evalEQ(state, Extent, DefinedSize);
|
||||||
state = state->Assume(ExtentMatchesSize, true);
|
state = state->Assume(ExtentMatchesSize, true);
|
||||||
|
|
||||||
SymbolRef Sym = RetVal.getAsLocSymbol();
|
SymbolRef Sym = RetVal.getAsLocSymbol();
|
||||||
|
@ -506,7 +506,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
|
||||||
ValueManager &ValMgr = C.getValueManager();
|
ValueManager &ValMgr = C.getValueManager();
|
||||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||||
|
|
||||||
DefinedOrUnknownSVal PtrEQ = svalBuilder.EvalEQ(state, Arg0Val, ValMgr.makeNull());
|
DefinedOrUnknownSVal PtrEQ = svalBuilder.evalEQ(state, Arg0Val, ValMgr.makeNull());
|
||||||
|
|
||||||
// If the ptr is NULL, the call is equivalent to malloc(size).
|
// If the ptr is NULL, the call is equivalent to malloc(size).
|
||||||
if (const GRState *stateEqual = state->Assume(PtrEQ, true)) {
|
if (const GRState *stateEqual = state->Assume(PtrEQ, true)) {
|
||||||
|
@ -527,7 +527,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
|
||||||
const Expr *Arg1 = CE->getArg(1);
|
const Expr *Arg1 = CE->getArg(1);
|
||||||
DefinedOrUnknownSVal Arg1Val =
|
DefinedOrUnknownSVal Arg1Val =
|
||||||
cast<DefinedOrUnknownSVal>(stateNotEqual->getSVal(Arg1));
|
cast<DefinedOrUnknownSVal>(stateNotEqual->getSVal(Arg1));
|
||||||
DefinedOrUnknownSVal SizeZero = svalBuilder.EvalEQ(stateNotEqual, Arg1Val,
|
DefinedOrUnknownSVal SizeZero = svalBuilder.evalEQ(stateNotEqual, Arg1Val,
|
||||||
ValMgr.makeIntValWithPtrWidth(0, false));
|
ValMgr.makeIntValWithPtrWidth(0, false));
|
||||||
|
|
||||||
if (const GRState *stateSizeZero = stateNotEqual->Assume(SizeZero, true)) {
|
if (const GRState *stateSizeZero = stateNotEqual->Assume(SizeZero, true)) {
|
||||||
|
@ -556,7 +556,7 @@ void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
|
||||||
|
|
||||||
SVal Count = state->getSVal(CE->getArg(0));
|
SVal Count = state->getSVal(CE->getArg(0));
|
||||||
SVal EleSize = state->getSVal(CE->getArg(1));
|
SVal EleSize = state->getSVal(CE->getArg(1));
|
||||||
SVal TotalSize = svalBuilder.EvalBinOp(state, BO_Mul, Count, EleSize,
|
SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, Count, EleSize,
|
||||||
ValMgr.getContext().getSizeType());
|
ValMgr.getContext().getSizeType());
|
||||||
|
|
||||||
SVal Zero = ValMgr.makeZeroVal(ValMgr.getContext().CharTy);
|
SVal Zero = ValMgr.makeZeroVal(ValMgr.getContext().CharTy);
|
||||||
|
@ -565,7 +565,7 @@ void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
|
||||||
C.addTransition(state);
|
C.addTransition(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MallocChecker::EvalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
|
void MallocChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
|
||||||
if (!SymReaper.hasDeadSymbols())
|
if (!SymReaper.hasDeadSymbols())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -595,7 +595,7 @@ void MallocChecker::EvalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
|
||||||
C.GenerateNode(state);
|
C.GenerateNode(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MallocChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
|
void MallocChecker::evalEndPath(GREndPathNodeBuilder &B, void *tag,
|
||||||
GRExprEngine &Eng) {
|
GRExprEngine &Eng) {
|
||||||
SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
|
SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
|
||||||
const GRState *state = B.getState();
|
const GRState *state = B.getState();
|
||||||
|
@ -639,7 +639,7 @@ void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
|
||||||
C.addTransition(state);
|
C.addTransition(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GRState *MallocChecker::EvalAssume(const GRState *state, SVal Cond,
|
const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond,
|
||||||
bool Assumption,
|
bool Assumption,
|
||||||
bool * /* respondsToCallback */) {
|
bool * /* respondsToCallback */) {
|
||||||
// If a symblic region is assumed to NULL, set its state to AllocateFailed.
|
// If a symblic region is assumed to NULL, set its state to AllocateFailed.
|
||||||
|
|
|
@ -22,10 +22,10 @@ namespace {
|
||||||
class OSAtomicChecker : public Checker {
|
class OSAtomicChecker : public Checker {
|
||||||
public:
|
public:
|
||||||
static void *getTag() { static int tag = 0; return &tag; }
|
static void *getTag() { static int tag = 0; return &tag; }
|
||||||
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
|
virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool EvalOSAtomicCompareAndSwap(CheckerContext &C, const CallExpr *CE);
|
bool evalOSAtomicCompareAndSwap(CheckerContext &C, const CallExpr *CE);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ void clang::RegisterOSAtomicChecker(GRExprEngine &Eng) {
|
||||||
Eng.registerCheck(new OSAtomicChecker());
|
Eng.registerCheck(new OSAtomicChecker());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSAtomicChecker::EvalCallExpr(CheckerContext &C,const CallExpr *CE) {
|
bool OSAtomicChecker::evalCallExpr(CheckerContext &C,const CallExpr *CE) {
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
const Expr *Callee = CE->getCallee();
|
const Expr *Callee = CE->getCallee();
|
||||||
SVal L = state->getSVal(Callee);
|
SVal L = state->getSVal(Callee);
|
||||||
|
@ -52,13 +52,13 @@ bool OSAtomicChecker::EvalCallExpr(CheckerContext &C,const CallExpr *CE) {
|
||||||
// Check for compare and swap.
|
// Check for compare and swap.
|
||||||
if (FName.startswith("OSAtomicCompareAndSwap") ||
|
if (FName.startswith("OSAtomicCompareAndSwap") ||
|
||||||
FName.startswith("objc_atomicCompareAndSwap"))
|
FName.startswith("objc_atomicCompareAndSwap"))
|
||||||
return EvalOSAtomicCompareAndSwap(C, CE);
|
return evalOSAtomicCompareAndSwap(C, CE);
|
||||||
|
|
||||||
// FIXME: Other atomics.
|
// FIXME: Other atomics.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
|
bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
|
||||||
const CallExpr *CE) {
|
const CallExpr *CE) {
|
||||||
// Not enough arguments to match OSAtomicCompareAndSwap?
|
// Not enough arguments to match OSAtomicCompareAndSwap?
|
||||||
if (CE->getNumArgs() != 3)
|
if (CE->getNumArgs() != 3)
|
||||||
|
@ -112,7 +112,7 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
|
||||||
dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
|
dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
|
||||||
LoadTy = TR->getValueType();
|
LoadTy = TR->getValueType();
|
||||||
}
|
}
|
||||||
Engine.EvalLoad(Tmp, theValueExpr, C.getPredecessor(),
|
Engine.evalLoad(Tmp, theValueExpr, C.getPredecessor(),
|
||||||
state, location, OSAtomicLoadTag, LoadTy);
|
state, location, OSAtomicLoadTag, LoadTy);
|
||||||
|
|
||||||
if (Tmp.empty()) {
|
if (Tmp.empty()) {
|
||||||
|
@ -145,7 +145,7 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
|
||||||
SValBuilder &svalBuilder = Engine.getSValBuilder();
|
SValBuilder &svalBuilder = Engine.getSValBuilder();
|
||||||
|
|
||||||
// Perform the comparison.
|
// Perform the comparison.
|
||||||
DefinedOrUnknownSVal Cmp = svalBuilder.EvalEQ(stateLoad,theValueVal,oldValueVal);
|
DefinedOrUnknownSVal Cmp = svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal);
|
||||||
|
|
||||||
const GRState *stateEqual = stateLoad->Assume(Cmp, true);
|
const GRState *stateEqual = stateLoad->Assume(Cmp, true);
|
||||||
|
|
||||||
|
@ -158,10 +158,10 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
|
||||||
// Handle implicit value casts.
|
// Handle implicit value casts.
|
||||||
if (const TypedRegion *R =
|
if (const TypedRegion *R =
|
||||||
dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
|
dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
|
||||||
val = svalBuilder.EvalCast(val,R->getValueType(), newValueExpr->getType());
|
val = svalBuilder.evalCast(val,R->getValueType(), newValueExpr->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine.EvalStore(TmpStore, NULL, theValueExpr, N,
|
Engine.evalStore(TmpStore, NULL, theValueExpr, N,
|
||||||
stateEqual, location, val, OSAtomicStoreTag);
|
stateEqual, location, val, OSAtomicStoreTag);
|
||||||
|
|
||||||
if (TmpStore.empty()) {
|
if (TmpStore.empty()) {
|
||||||
|
|
|
@ -227,7 +227,7 @@ public:
|
||||||
/// For DerivedToBase casts, create a CXXBaseObjectRegion and return it.
|
/// For DerivedToBase casts, create a CXXBaseObjectRegion and return it.
|
||||||
virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType);
|
virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType);
|
||||||
|
|
||||||
SVal EvalBinOp(BinaryOperator::Opcode Op,Loc L, NonLoc R, QualType resultTy);
|
SVal evalBinOp(BinaryOperator::Opcode Op,Loc L, NonLoc R, QualType resultTy);
|
||||||
|
|
||||||
Store getInitialStore(const LocationContext *InitLoc) {
|
Store getInitialStore(const LocationContext *InitLoc) {
|
||||||
return RBFactory.getEmptyMap().getRoot();
|
return RBFactory.getEmptyMap().getRoot();
|
||||||
|
@ -819,7 +819,7 @@ SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType basePtrType) {
|
||||||
// Pointer arithmetic.
|
// Pointer arithmetic.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
|
SVal RegionStoreManager::evalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
|
||||||
QualType resultTy) {
|
QualType resultTy) {
|
||||||
// Assume the base location is MemRegionVal.
|
// Assume the base location is MemRegionVal.
|
||||||
if (!isa<loc::MemRegionVal>(L))
|
if (!isa<loc::MemRegionVal>(L))
|
||||||
|
@ -1307,7 +1307,7 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) {
|
||||||
if (const IntegerLiteral *IL =
|
if (const IntegerLiteral *IL =
|
||||||
dyn_cast<IntegerLiteral>(Init->IgnoreParenCasts())) {
|
dyn_cast<IntegerLiteral>(Init->IgnoreParenCasts())) {
|
||||||
const nonloc::ConcreteInt &V = ValMgr.makeIntVal(IL);
|
const nonloc::ConcreteInt &V = ValMgr.makeIntVal(IL);
|
||||||
return ValMgr.getSValBuilder().EvalCast(V, Init->getType(),
|
return ValMgr.getSValBuilder().evalCast(V, Init->getType(),
|
||||||
IL->getType());
|
IL->getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
|
|
||||||
SVal SValBuilder::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
SVal SValBuilder::evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
||||||
SVal L, SVal R, QualType T) {
|
SVal L, SVal R, QualType T) {
|
||||||
|
|
||||||
if (L.isUndef() || R.isUndef())
|
if (L.isUndef() || R.isUndef())
|
||||||
|
@ -29,9 +29,9 @@ SVal SValBuilder::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
||||||
|
|
||||||
if (isa<Loc>(L)) {
|
if (isa<Loc>(L)) {
|
||||||
if (isa<Loc>(R))
|
if (isa<Loc>(R))
|
||||||
return EvalBinOpLL(ST, Op, cast<Loc>(L), cast<Loc>(R), T);
|
return evalBinOpLL(ST, Op, cast<Loc>(L), cast<Loc>(R), T);
|
||||||
|
|
||||||
return EvalBinOpLN(ST, Op, cast<Loc>(L), cast<NonLoc>(R), T);
|
return evalBinOpLN(ST, Op, cast<Loc>(L), cast<NonLoc>(R), T);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isa<Loc>(R)) {
|
if (isa<Loc>(R)) {
|
||||||
|
@ -40,21 +40,21 @@ SVal SValBuilder::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
||||||
assert(Op == BO_Add);
|
assert(Op == BO_Add);
|
||||||
|
|
||||||
// Commute the operands.
|
// Commute the operands.
|
||||||
return EvalBinOpLN(ST, Op, cast<Loc>(R), cast<NonLoc>(L), T);
|
return evalBinOpLN(ST, Op, cast<Loc>(R), cast<NonLoc>(L), T);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EvalBinOpNN(ST, Op, cast<NonLoc>(L), cast<NonLoc>(R), T);
|
return evalBinOpNN(ST, Op, cast<NonLoc>(L), cast<NonLoc>(R), T);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinedOrUnknownSVal SValBuilder::EvalEQ(const GRState *ST,
|
DefinedOrUnknownSVal SValBuilder::evalEQ(const GRState *ST,
|
||||||
DefinedOrUnknownSVal L,
|
DefinedOrUnknownSVal L,
|
||||||
DefinedOrUnknownSVal R) {
|
DefinedOrUnknownSVal R) {
|
||||||
return cast<DefinedOrUnknownSVal>(EvalBinOp(ST, BO_EQ, L, R,
|
return cast<DefinedOrUnknownSVal>(evalBinOp(ST, BO_EQ, L, R,
|
||||||
ValMgr.getContext().IntTy));
|
ValMgr.getContext().IntTy));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: should rewrite according to the cast kind.
|
// FIXME: should rewrite according to the cast kind.
|
||||||
SVal SValBuilder::EvalCast(SVal val, QualType castTy, QualType originalTy) {
|
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
|
||||||
if (val.isUnknownOrUndef() || castTy == originalTy)
|
if (val.isUnknownOrUndef() || castTy == originalTy)
|
||||||
return val;
|
return val;
|
||||||
|
|
||||||
|
@ -72,11 +72,11 @@ SVal SValBuilder::EvalCast(SVal val, QualType castTy, QualType originalTy) {
|
||||||
|
|
||||||
// Check for casts from integers to integers.
|
// Check for casts from integers to integers.
|
||||||
if (castTy->isIntegerType() && originalTy->isIntegerType())
|
if (castTy->isIntegerType() && originalTy->isIntegerType())
|
||||||
return EvalCastNL(cast<NonLoc>(val), castTy);
|
return evalCastNL(cast<NonLoc>(val), castTy);
|
||||||
|
|
||||||
// Check for casts from pointers to integers.
|
// Check for casts from pointers to integers.
|
||||||
if (castTy->isIntegerType() && Loc::IsLocType(originalTy))
|
if (castTy->isIntegerType() && Loc::IsLocType(originalTy))
|
||||||
return EvalCastL(cast<Loc>(val), castTy);
|
return evalCastL(cast<Loc>(val), castTy);
|
||||||
|
|
||||||
// Check for casts from integers to pointers.
|
// Check for casts from integers to pointers.
|
||||||
if (Loc::IsLocType(castTy) && originalTy->isIntegerType()) {
|
if (Loc::IsLocType(castTy) && originalTy->isIntegerType()) {
|
||||||
|
@ -115,7 +115,7 @@ SVal SValBuilder::EvalCast(SVal val, QualType castTy, QualType originalTy) {
|
||||||
// need the original decayed type.
|
// need the original decayed type.
|
||||||
// QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
|
// QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
|
||||||
// QualType pointerTy = C.getPointerType(elemTy);
|
// QualType pointerTy = C.getPointerType(elemTy);
|
||||||
return EvalCastL(cast<Loc>(val), castTy);
|
return evalCastL(cast<Loc>(val), castTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for casts from a region to a specific type.
|
// Check for casts from a region to a specific type.
|
||||||
|
@ -157,13 +157,13 @@ SVal SValBuilder::EvalCast(SVal val, QualType castTy, QualType originalTy) {
|
||||||
|
|
||||||
// Delegate to store manager to get the result of casting a region to a
|
// Delegate to store manager to get the result of casting a region to a
|
||||||
// different type. If the MemRegion* returned is NULL, this expression
|
// different type. If the MemRegion* returned is NULL, this expression
|
||||||
// evaluates to UnknownVal.
|
// Evaluates to UnknownVal.
|
||||||
R = storeMgr.CastRegion(R, castTy);
|
R = storeMgr.CastRegion(R, castTy);
|
||||||
return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
|
return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchCast:
|
DispatchCast:
|
||||||
// All other cases.
|
// All other cases.
|
||||||
return isa<Loc>(val) ? EvalCastL(cast<Loc>(val), castTy)
|
return isa<Loc>(val) ? evalCastL(cast<Loc>(val), castTy)
|
||||||
: EvalCastNL(cast<NonLoc>(val), castTy);
|
: evalCastNL(cast<NonLoc>(val), castTy);
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,7 +225,7 @@ SVal nonloc::ConcreteInt::evalBinOp(ValueManager &ValMgr,
|
||||||
BinaryOperator::Opcode Op,
|
BinaryOperator::Opcode Op,
|
||||||
const nonloc::ConcreteInt& R) const {
|
const nonloc::ConcreteInt& R) const {
|
||||||
const llvm::APSInt* X =
|
const llvm::APSInt* X =
|
||||||
ValMgr.getBasicValueFactory().EvaluateAPSInt(Op, getValue(), R.getValue());
|
ValMgr.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
|
||||||
|
|
||||||
if (X)
|
if (X)
|
||||||
return nonloc::ConcreteInt(*X);
|
return nonloc::ConcreteInt(*X);
|
||||||
|
@ -246,14 +246,14 @@ nonloc::ConcreteInt nonloc::ConcreteInt::evalMinus(ValueManager &ValMgr) const {
|
||||||
// Transfer function dispatch for Locs.
|
// Transfer function dispatch for Locs.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
|
SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
|
||||||
BinaryOperator::Opcode Op,
|
BinaryOperator::Opcode Op,
|
||||||
const loc::ConcreteInt& R) const {
|
const loc::ConcreteInt& R) const {
|
||||||
|
|
||||||
assert (Op == BO_Add || Op == BO_Sub ||
|
assert (Op == BO_Add || Op == BO_Sub ||
|
||||||
(Op >= BO_LT && Op <= BO_NE));
|
(Op >= BO_LT && Op <= BO_NE));
|
||||||
|
|
||||||
const llvm::APSInt* X = BasicVals.EvaluateAPSInt(Op, getValue(), R.getValue());
|
const llvm::APSInt* X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
|
||||||
|
|
||||||
if (X)
|
if (X)
|
||||||
return loc::ConcreteInt(*X);
|
return loc::ConcreteInt(*X);
|
||||||
|
|
|
@ -19,23 +19,23 @@ using namespace clang;
|
||||||
namespace {
|
namespace {
|
||||||
class SimpleSValBuilder : public SValBuilder {
|
class SimpleSValBuilder : public SValBuilder {
|
||||||
protected:
|
protected:
|
||||||
virtual SVal EvalCastNL(NonLoc val, QualType castTy);
|
virtual SVal evalCastNL(NonLoc val, QualType castTy);
|
||||||
virtual SVal EvalCastL(Loc val, QualType castTy);
|
virtual SVal evalCastL(Loc val, QualType castTy);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SimpleSValBuilder(ValueManager &valMgr) : SValBuilder(valMgr) {}
|
SimpleSValBuilder(ValueManager &valMgr) : SValBuilder(valMgr) {}
|
||||||
virtual ~SimpleSValBuilder() {}
|
virtual ~SimpleSValBuilder() {}
|
||||||
|
|
||||||
virtual SVal EvalMinus(NonLoc val);
|
virtual SVal evalMinus(NonLoc val);
|
||||||
virtual SVal EvalComplement(NonLoc val);
|
virtual SVal evalComplement(NonLoc val);
|
||||||
virtual SVal EvalBinOpNN(const GRState *state, BinaryOperator::Opcode op,
|
virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode op,
|
||||||
NonLoc lhs, NonLoc rhs, QualType resultTy);
|
NonLoc lhs, NonLoc rhs, QualType resultTy);
|
||||||
virtual SVal EvalBinOpLL(const GRState *state, BinaryOperator::Opcode op,
|
virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode op,
|
||||||
Loc lhs, Loc rhs, QualType resultTy);
|
Loc lhs, Loc rhs, QualType resultTy);
|
||||||
virtual SVal EvalBinOpLN(const GRState *state, BinaryOperator::Opcode op,
|
virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode op,
|
||||||
Loc lhs, NonLoc rhs, QualType resultTy);
|
Loc lhs, NonLoc rhs, QualType resultTy);
|
||||||
|
|
||||||
/// getKnownValue - Evaluates a given SVal. If the SVal has only one possible
|
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible
|
||||||
/// (integer) value, that value is returned. Otherwise, returns NULL.
|
/// (integer) value, that value is returned. Otherwise, returns NULL.
|
||||||
virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V);
|
virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V);
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ SValBuilder *clang::createSimpleSValBuilder(ValueManager &valMgr) {
|
||||||
// Transfer function for Casts.
|
// Transfer function for Casts.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
SVal SimpleSValBuilder::EvalCastNL(NonLoc val, QualType castTy) {
|
SVal SimpleSValBuilder::evalCastNL(NonLoc val, QualType castTy) {
|
||||||
|
|
||||||
bool isLocType = Loc::IsLocType(castTy);
|
bool isLocType = Loc::IsLocType(castTy);
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ SVal SimpleSValBuilder::EvalCastNL(NonLoc val, QualType castTy) {
|
||||||
return ValMgr.makeIntVal(i);
|
return ValMgr.makeIntVal(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
SVal SimpleSValBuilder::EvalCastL(Loc val, QualType castTy) {
|
SVal SimpleSValBuilder::evalCastL(Loc val, QualType castTy) {
|
||||||
|
|
||||||
// Casts from pointers -> pointers, just return the lval.
|
// Casts from pointers -> pointers, just return the lval.
|
||||||
//
|
//
|
||||||
|
@ -142,7 +142,7 @@ SVal SimpleSValBuilder::EvalCastL(Loc val, QualType castTy) {
|
||||||
// Transfer function for unary operators.
|
// Transfer function for unary operators.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
SVal SimpleSValBuilder::EvalMinus(NonLoc val) {
|
SVal SimpleSValBuilder::evalMinus(NonLoc val) {
|
||||||
switch (val.getSubKind()) {
|
switch (val.getSubKind()) {
|
||||||
case nonloc::ConcreteIntKind:
|
case nonloc::ConcreteIntKind:
|
||||||
return cast<nonloc::ConcreteInt>(val).evalMinus(ValMgr);
|
return cast<nonloc::ConcreteInt>(val).evalMinus(ValMgr);
|
||||||
|
@ -151,7 +151,7 @@ SVal SimpleSValBuilder::EvalMinus(NonLoc val) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SVal SimpleSValBuilder::EvalComplement(NonLoc X) {
|
SVal SimpleSValBuilder::evalComplement(NonLoc X) {
|
||||||
switch (X.getSubKind()) {
|
switch (X.getSubKind()) {
|
||||||
case nonloc::ConcreteIntKind:
|
case nonloc::ConcreteIntKind:
|
||||||
return cast<nonloc::ConcreteInt>(X).evalComplement(ValMgr);
|
return cast<nonloc::ConcreteInt>(X).evalComplement(ValMgr);
|
||||||
|
@ -254,11 +254,11 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Idempotent ops (like a*1) can still change the type of an expression.
|
// Idempotent ops (like a*1) can still change the type of an expression.
|
||||||
// Wrap the LHS up in a NonLoc again and let EvalCastNL do the dirty work.
|
// Wrap the LHS up in a NonLoc again and let evalCastNL do the dirty work.
|
||||||
if (isIdempotent) {
|
if (isIdempotent) {
|
||||||
if (SymbolRef LHSSym = dyn_cast<SymbolData>(LHS))
|
if (SymbolRef LHSSym = dyn_cast<SymbolData>(LHS))
|
||||||
return EvalCastNL(nonloc::SymbolVal(LHSSym), resultTy);
|
return evalCastNL(nonloc::SymbolVal(LHSSym), resultTy);
|
||||||
return EvalCastNL(nonloc::SymExprVal(LHS), resultTy);
|
return evalCastNL(nonloc::SymExprVal(LHS), resultTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we reach this point, the expression cannot be simplified.
|
// If we reach this point, the expression cannot be simplified.
|
||||||
|
@ -266,7 +266,7 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
|
||||||
return ValMgr.makeNonLoc(LHS, op, RHS, resultTy);
|
return ValMgr.makeNonLoc(LHS, op, RHS, resultTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
SVal SimpleSValBuilder::EvalBinOpNN(const GRState *state,
|
SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
|
||||||
BinaryOperator::Opcode op,
|
BinaryOperator::Opcode op,
|
||||||
NonLoc lhs, NonLoc rhs,
|
NonLoc lhs, NonLoc rhs,
|
||||||
QualType resultTy) {
|
QualType resultTy) {
|
||||||
|
@ -288,7 +288,7 @@ SVal SimpleSValBuilder::EvalBinOpNN(const GRState *state,
|
||||||
return ValMgr.makeIntVal(0, resultTy);
|
return ValMgr.makeIntVal(0, resultTy);
|
||||||
case BO_Or:
|
case BO_Or:
|
||||||
case BO_And:
|
case BO_And:
|
||||||
return EvalCastNL(lhs, resultTy);
|
return evalCastNL(lhs, resultTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -299,7 +299,7 @@ SVal SimpleSValBuilder::EvalBinOpNN(const GRState *state,
|
||||||
Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc();
|
Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc();
|
||||||
switch (rhs.getSubKind()) {
|
switch (rhs.getSubKind()) {
|
||||||
case nonloc::LocAsIntegerKind:
|
case nonloc::LocAsIntegerKind:
|
||||||
return EvalBinOpLL(state, op, lhsL,
|
return evalBinOpLL(state, op, lhsL,
|
||||||
cast<nonloc::LocAsInteger>(rhs).getLoc(),
|
cast<nonloc::LocAsInteger>(rhs).getLoc(),
|
||||||
resultTy);
|
resultTy);
|
||||||
case nonloc::ConcreteIntKind: {
|
case nonloc::ConcreteIntKind: {
|
||||||
|
@ -308,7 +308,7 @@ SVal SimpleSValBuilder::EvalBinOpNN(const GRState *state,
|
||||||
llvm::APSInt i = cast<nonloc::ConcreteInt>(rhs).getValue();
|
llvm::APSInt i = cast<nonloc::ConcreteInt>(rhs).getValue();
|
||||||
i.setIsUnsigned(true);
|
i.setIsUnsigned(true);
|
||||||
i.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy));
|
i.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy));
|
||||||
return EvalBinOpLL(state, op, lhsL, ValMgr.makeLoc(i), resultTy);
|
return evalBinOpLL(state, op, lhsL, ValMgr.makeLoc(i), resultTy);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -402,9 +402,9 @@ SVal SimpleSValBuilder::EvalBinOpNN(const GRState *state,
|
||||||
|
|
||||||
const llvm::APSInt *newRHS;
|
const llvm::APSInt *newRHS;
|
||||||
if (lop == op)
|
if (lop == op)
|
||||||
newRHS = BVF.EvaluateAPSInt(BO_Add, first, second);
|
newRHS = BVF.evalAPSInt(BO_Add, first, second);
|
||||||
else
|
else
|
||||||
newRHS = BVF.EvaluateAPSInt(BO_Sub, first, second);
|
newRHS = BVF.evalAPSInt(BO_Sub, first, second);
|
||||||
return MakeSymIntVal(symIntExpr->getLHS(), lop, *newRHS, resultTy);
|
return MakeSymIntVal(symIntExpr->getLHS(), lop, *newRHS, resultTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,13 +515,13 @@ SVal SimpleSValBuilder::EvalBinOpNN(const GRState *state,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: all this logic will change if/when we have MemRegion::getLocation().
|
// FIXME: all this logic will change if/when we have MemRegion::getLocation().
|
||||||
SVal SimpleSValBuilder::EvalBinOpLL(const GRState *state,
|
SVal SimpleSValBuilder::evalBinOpLL(const GRState *state,
|
||||||
BinaryOperator::Opcode op,
|
BinaryOperator::Opcode op,
|
||||||
Loc lhs, Loc rhs,
|
Loc lhs, Loc rhs,
|
||||||
QualType resultTy) {
|
QualType resultTy) {
|
||||||
// Only comparisons and subtractions are valid operations on two pointers.
|
// Only comparisons and subtractions are valid operations on two pointers.
|
||||||
// See [C99 6.5.5 through 6.5.14] or [C++0x 5.6 through 5.15].
|
// See [C99 6.5.5 through 6.5.14] or [C++0x 5.6 through 5.15].
|
||||||
// However, if a pointer is casted to an integer, EvalBinOpNN may end up
|
// However, if a pointer is casted to an integer, evalBinOpNN may end up
|
||||||
// calling this function with another operation (PR7527). We don't attempt to
|
// calling this function with another operation (PR7527). We don't attempt to
|
||||||
// model this for now, but it could be useful, particularly when the
|
// model this for now, but it could be useful, particularly when the
|
||||||
// "location" is actually an integer value that's been passed through a void*.
|
// "location" is actually an integer value that's been passed through a void*.
|
||||||
|
@ -559,7 +559,7 @@ SVal SimpleSValBuilder::EvalBinOpLL(const GRState *state,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case BO_Sub:
|
case BO_Sub:
|
||||||
return EvalCastL(lhs, resultTy);
|
return evalCastL(lhs, resultTy);
|
||||||
case BO_EQ:
|
case BO_EQ:
|
||||||
case BO_LE:
|
case BO_LE:
|
||||||
case BO_LT:
|
case BO_LT:
|
||||||
|
@ -593,9 +593,9 @@ SVal SimpleSValBuilder::EvalBinOpLL(const GRState *state,
|
||||||
// If both operands are constants, just perform the operation.
|
// If both operands are constants, just perform the operation.
|
||||||
if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) {
|
if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) {
|
||||||
BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
|
BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
|
||||||
SVal ResultVal = cast<loc::ConcreteInt>(lhs).EvalBinOp(BVF, op, *rInt);
|
SVal ResultVal = cast<loc::ConcreteInt>(lhs).evalBinOp(BVF, op, *rInt);
|
||||||
if (Loc *Result = dyn_cast<Loc>(&ResultVal))
|
if (Loc *Result = dyn_cast<Loc>(&ResultVal))
|
||||||
return EvalCastL(*Result, resultTy);
|
return evalCastL(*Result, resultTy);
|
||||||
else
|
else
|
||||||
return UnknownVal();
|
return UnknownVal();
|
||||||
}
|
}
|
||||||
|
@ -640,7 +640,7 @@ SVal SimpleSValBuilder::EvalBinOpLL(const GRState *state,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case BO_Sub:
|
case BO_Sub:
|
||||||
return EvalCastL(lhs, resultTy);
|
return evalCastL(lhs, resultTy);
|
||||||
case BO_EQ:
|
case BO_EQ:
|
||||||
case BO_LT:
|
case BO_LT:
|
||||||
case BO_LE:
|
case BO_LE:
|
||||||
|
@ -705,7 +705,7 @@ SVal SimpleSValBuilder::EvalBinOpLL(const GRState *state,
|
||||||
NonLoc *LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
|
NonLoc *LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
|
||||||
if (!LeftIndex)
|
if (!LeftIndex)
|
||||||
return UnknownVal();
|
return UnknownVal();
|
||||||
LeftIndexVal = EvalCastNL(*LeftIndex, resultTy);
|
LeftIndexVal = evalCastNL(*LeftIndex, resultTy);
|
||||||
LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
|
LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
|
||||||
if (!LeftIndex)
|
if (!LeftIndex)
|
||||||
return UnknownVal();
|
return UnknownVal();
|
||||||
|
@ -715,14 +715,14 @@ SVal SimpleSValBuilder::EvalBinOpLL(const GRState *state,
|
||||||
NonLoc *RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
|
NonLoc *RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
|
||||||
if (!RightIndex)
|
if (!RightIndex)
|
||||||
return UnknownVal();
|
return UnknownVal();
|
||||||
RightIndexVal = EvalCastNL(*RightIndex, resultTy);
|
RightIndexVal = evalCastNL(*RightIndex, resultTy);
|
||||||
RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
|
RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
|
||||||
if (!RightIndex)
|
if (!RightIndex)
|
||||||
return UnknownVal();
|
return UnknownVal();
|
||||||
|
|
||||||
// Actually perform the operation.
|
// Actually perform the operation.
|
||||||
// EvalBinOpNN expects the two indexes to already be the right type.
|
// evalBinOpNN expects the two indexes to already be the right type.
|
||||||
return EvalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy);
|
return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the element indexes aren't comparable, see if the raw offsets are.
|
// If the element indexes aren't comparable, see if the raw offsets are.
|
||||||
|
@ -812,7 +812,7 @@ SVal SimpleSValBuilder::EvalBinOpLL(const GRState *state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SVal SimpleSValBuilder::EvalBinOpLN(const GRState *state,
|
SVal SimpleSValBuilder::evalBinOpLN(const GRState *state,
|
||||||
BinaryOperator::Opcode op,
|
BinaryOperator::Opcode op,
|
||||||
Loc lhs, NonLoc rhs, QualType resultTy) {
|
Loc lhs, NonLoc rhs, QualType resultTy) {
|
||||||
// Special case: 'rhs' is an integer that has the same width as a pointer and
|
// Special case: 'rhs' is an integer that has the same width as a pointer and
|
||||||
|
@ -829,7 +829,7 @@ SVal SimpleSValBuilder::EvalBinOpLN(const GRState *state,
|
||||||
if (x->isSigned())
|
if (x->isSigned())
|
||||||
x = &ValMgr.getBasicValueFactory().getValue(*x, true);
|
x = &ValMgr.getBasicValueFactory().getValue(*x, true);
|
||||||
|
|
||||||
return EvalBinOpLL(state, op, lhs, loc::ConcreteInt(*x), resultTy);
|
return evalBinOpLL(state, op, lhs, loc::ConcreteInt(*x), resultTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -868,7 +868,7 @@ SVal SimpleSValBuilder::EvalBinOpLN(const GRState *state,
|
||||||
|
|
||||||
|
|
||||||
// Delegate remaining pointer arithmetic to the StoreManager.
|
// Delegate remaining pointer arithmetic to the StoreManager.
|
||||||
return state->getStateManager().getStoreManager().EvalBinOp(op, lhs,
|
return state->getStateManager().getStoreManager().evalBinOp(op, lhs,
|
||||||
rhs, resultTy);
|
rhs, resultTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
return &x;
|
return &x;
|
||||||
}
|
}
|
||||||
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
|
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
|
||||||
void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
|
void evalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
|
||||||
private:
|
private:
|
||||||
void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
|
void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
|
||||||
SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
|
SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
|
||||||
|
@ -129,7 +129,7 @@ void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackAddrLeakChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
|
void StackAddrLeakChecker::evalEndPath(GREndPathNodeBuilder &B, void *tag,
|
||||||
GRExprEngine &Eng) {
|
GRExprEngine &Eng) {
|
||||||
SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
|
SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
|
||||||
const GRState *state = B.getState();
|
const GRState *state = B.getState();
|
||||||
|
|
|
@ -225,9 +225,9 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const Loc *L = dyn_cast<Loc>(&V))
|
if (const Loc *L = dyn_cast<Loc>(&V))
|
||||||
return ValMgr.getSValBuilder().EvalCastL(*L, castTy);
|
return ValMgr.getSValBuilder().evalCastL(*L, castTy);
|
||||||
else if (const NonLoc *NL = dyn_cast<NonLoc>(&V))
|
else if (const NonLoc *NL = dyn_cast<NonLoc>(&V))
|
||||||
return ValMgr.getSValBuilder().EvalCastNL(*NL, castTy);
|
return ValMgr.getSValBuilder().evalCastNL(*NL, castTy);
|
||||||
|
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,9 +72,9 @@ public:
|
||||||
return &x;
|
return &x;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
|
virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||||
void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
|
void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
|
||||||
void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
|
void evalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
|
||||||
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
|
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -115,7 +115,7 @@ void clang::RegisterStreamChecker(GRExprEngine &Eng) {
|
||||||
Eng.registerCheck(new StreamChecker());
|
Eng.registerCheck(new StreamChecker());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||||
const GRState *state = C.getState();
|
const GRState *state = C.getState();
|
||||||
const Expr *Callee = CE->getCallee();
|
const Expr *Callee = CE->getCallee();
|
||||||
SVal L = state->getSVal(Callee);
|
SVal L = state->getSVal(Callee);
|
||||||
|
@ -395,7 +395,7 @@ const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
|
||||||
return state->set<StreamState>(Sym, StreamState::getClosed(CE));
|
return state->set<StreamState>(Sym, StreamState::getClosed(CE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamChecker::EvalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
|
void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
|
||||||
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
|
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
|
||||||
E = SymReaper.dead_end(); I != E; ++I) {
|
E = SymReaper.dead_end(); I != E; ++I) {
|
||||||
SymbolRef Sym = *I;
|
SymbolRef Sym = *I;
|
||||||
|
@ -418,7 +418,7 @@ void StreamChecker::EvalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
|
void StreamChecker::evalEndPath(GREndPathNodeBuilder &B, void *tag,
|
||||||
GRExprEngine &Eng) {
|
GRExprEngine &Eng) {
|
||||||
SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
|
SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
|
||||||
const GRState *state = B.getState();
|
const GRState *state = B.getState();
|
||||||
|
|
|
@ -101,7 +101,7 @@ static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
|
||||||
NonLoc ocreateFlag =
|
NonLoc ocreateFlag =
|
||||||
cast<NonLoc>(C.getValueManager().makeIntVal(UC.Val_O_CREAT.getValue(),
|
cast<NonLoc>(C.getValueManager().makeIntVal(UC.Val_O_CREAT.getValue(),
|
||||||
oflagsEx->getType()));
|
oflagsEx->getType()));
|
||||||
SVal maskedFlagsUC = C.getSValBuilder().EvalBinOpNN(state, BO_And,
|
SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
|
||||||
oflags, ocreateFlag,
|
oflags, ocreateFlag,
|
||||||
oflagsEx->getType());
|
oflagsEx->getType());
|
||||||
if (maskedFlagsUC.isUnknownOrUndef())
|
if (maskedFlagsUC.isUnknownOrUndef())
|
||||||
|
|
|
@ -110,21 +110,21 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
|
||||||
ValueManager &ValMgr = C.getValueManager();
|
ValueManager &ValMgr = C.getValueManager();
|
||||||
SValBuilder &SV = ValMgr.getSValBuilder();
|
SValBuilder &SV = ValMgr.getSValBuilder();
|
||||||
QualType SizeTy = Ctx.getSizeType();
|
QualType SizeTy = Ctx.getSizeType();
|
||||||
NonLoc ArrayLength = cast<NonLoc>(SV.EvalCast(sizeD, SizeTy, SE->getType()));
|
NonLoc ArrayLength = cast<NonLoc>(SV.evalCast(sizeD, SizeTy, SE->getType()));
|
||||||
|
|
||||||
// Get the element size.
|
// Get the element size.
|
||||||
CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
|
CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
|
||||||
SVal EleSizeVal = ValMgr.makeIntVal(EleSize.getQuantity(), SizeTy);
|
SVal EleSizeVal = ValMgr.makeIntVal(EleSize.getQuantity(), SizeTy);
|
||||||
|
|
||||||
// Multiply the array length by the element size.
|
// Multiply the array length by the element size.
|
||||||
SVal ArraySizeVal = SV.EvalBinOpNN(state, BO_Mul, ArrayLength,
|
SVal ArraySizeVal = SV.evalBinOpNN(state, BO_Mul, ArrayLength,
|
||||||
cast<NonLoc>(EleSizeVal), SizeTy);
|
cast<NonLoc>(EleSizeVal), SizeTy);
|
||||||
|
|
||||||
// Finally, Assume that the array's extent matches the given size.
|
// Finally, Assume that the array's extent matches the given size.
|
||||||
const LocationContext *LC = C.getPredecessor()->getLocationContext();
|
const LocationContext *LC = C.getPredecessor()->getLocationContext();
|
||||||
DefinedOrUnknownSVal Extent = state->getRegion(VD, LC)->getExtent(ValMgr);
|
DefinedOrUnknownSVal Extent = state->getRegion(VD, LC)->getExtent(ValMgr);
|
||||||
DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
|
DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
|
||||||
DefinedOrUnknownSVal SizeIsKnown = SV.EvalEQ(state, Extent, ArraySize);
|
DefinedOrUnknownSVal SizeIsKnown = SV.evalEQ(state, Extent, ArraySize);
|
||||||
state = state->Assume(SizeIsKnown, true);
|
state = state->Assume(SizeIsKnown, true);
|
||||||
|
|
||||||
// Assume should not fail at this point.
|
// Assume should not fail at this point.
|
||||||
|
|
|
@ -67,7 +67,7 @@ SVal ValueManager::convertToArrayIndex(SVal V) {
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
return svalBuilder->EvalCastNL(cast<NonLoc>(V), ArrayIndexTy);
|
return svalBuilder->evalCastNL(cast<NonLoc>(V), ArrayIndexTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinedOrUnknownSVal
|
DefinedOrUnknownSVal
|
||||||
|
|
Loading…
Reference in New Issue