void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){
+ if (VarDecl* VD = dyn_cast<VarDecl>(D->getDecl()))
+ if (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD)) {
+
+ StateTy StOld = Pred->getState();
+ StateTy St = Symbolicate(StOld, VD);
+
+ if (!(St == StOld)) {
+ if (D != CurrentStmt)
+ Nodify(Dst, D, Pred, St);
+ else
+ Nodify(Dst, D, Pred, SetRVal(St, D, GetRVal(St, D)));
+
+ return;
+ }
+ }
+
if (D != CurrentStmt) {
Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
return;
Ex = Ex->IgnoreParens();
- if (isa<DeclRefExpr>(Ex)) {
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex)) {
+
+ if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD)) {
+
+ StateTy StOld = Pred->getState();
+ StateTy St = Symbolicate(StOld, VD);
+
+ if (!(St == StOld)) {
+ Nodify(Dst, Ex, Pred, St);
+ return;
+ }
+ }
+
Dst.Add(Pred);
return;
}
if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
&& RHS->getType()->isIntegerType()) {
+
+ // Check if the denominator is uninitialized.
- // Check for divide/remaindner-by-zero.
-
- // First, "assume" that the denominator is 0.
+ if (RightV.isUninit()) {
+ NodeTy* DivUninit = Builder->generateNode(B, St, N2);
+
+ if (DivUninit) {
+ DivUninit->markAsSink();
+ BadDivides.insert(DivUninit);
+ }
+
+ continue;
+ }
+
+ // Check for divide/remainder-by-zero.
+ //
+ // First, "assume" that the denominator is 0 or uninitialized.
bool isFeasible = false;
- StateTy ZeroSt = Assume(St, RightV, false, isFeasible);
+ StateTy ZeroSt = Assume(St, RightV, false,isFeasible);
if (isFeasible) {
NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2);
if (DivZeroNode) {
DivZeroNode->markAsSink();
- DivZeroes.insert(DivZeroNode);
+ BadDivides.insert(DivZeroNode);
}
}
if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
&& RHS->getType()->isIntegerType()) {
- // Check for divide/remainder-by-zero.
-
+ // Check if the denominator is uninitialized.
+
+ if (RightV.isUninit()) {
+ NodeTy* DivUninit = Builder->generateNode(B, St, N2);
+
+ if (DivUninit) {
+ DivUninit->markAsSink();
+ BadDivides.insert(DivUninit);
+ }
+
+ continue;
+ }
+
// First, "assume" that the denominator is 0.
bool isFeasible = false;
if (DivZeroNode) {
DivZeroNode->markAsSink();
- DivZeroes.insert(DivZeroNode);
+ BadDivides.insert(DivZeroNode);
}
}
return nonlval::ConcreteInt(ValMgr.getTruthValue(b));
}
-RVal RVal::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) {
+RVal RVal::GetSymbolValue(SymbolManager& SymMgr, VarDecl* D) {
QualType T = D->getType();
using namespace clang;
-SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
+SymbolID SymbolManager::getSymbol(VarDecl* D) {
+
+ assert (isa<ParmVarDecl>(D) || D->hasGlobalStorage());
+
SymbolID& X = DataToSymbol[getKey(D)];
if (!X.isInitialized()) {
X = SymbolToData.size();
- SymbolToData.push_back(SymbolDataParmVar(D));
+
+ if (ParmVarDecl* VD = dyn_cast<ParmVarDecl>(D))
+ SymbolToData.push_back(SymbolDataParmVar(VD));
+ else
+ SymbolToData.push_back(SymbolDataGlobalVar(D));
}
return X;
-}
-
+}
+
SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
SymbolID& X = DataToSymbol[getKey(sym)];
case ParmKind:
return cast<SymbolDataParmVar>(this)->getDecl()->getType();
+
+ case GlobalKind:
+ return cast<SymbolDataGlobalVar>(this)->getDecl()->getType();
case ContentsOfKind: {
SymbolID x = cast<SymbolDataContentsOf>(this)->getSymbol();
// Iterate over the variable bindings.
for (ValueState::vb_iterator I = St.vb_begin(), E = St.vb_end(); I!=E ; ++I)
- if (Liveness.isLive(Loc, I.getKey()))
+ if (Liveness.isLive(Loc, I.getKey())) {
WList.push_back(I.getKey());
+
+ RVal X = I.getData();
+
+ for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
+ SI != SE; ++SI) {
+ MarkedSymbols.insert(*SI);
+ }
+ }
// Perform the mark-and-sweep.
/// taking a dereference on an uninitialized value.
BadDerefTy UninitDeref;
- /// DivZeroes - Nodes in the ExplodedGraph that result from evaluating
- /// a divide-by-zero.
- DivZerosTy DivZeroes;
+ /// BadDivides - Nodes in the ExplodedGraph that result from evaluating
+ /// a divide-by-zero or divide-by-uninitialized.
+ DivZerosTy BadDivides;
bool StateCleaned;
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
- StateTy getInitialState() {
- StateTy St = StateMgr.getInitialState();
-
- // Iterate the parameters.
- FunctionDecl& F = G.getFunctionDecl();
-
- for (FunctionDecl::param_iterator I = F.param_begin(), E = F.param_end();
- I != E; ++I) {
- St = SetRVal(St, lval::DeclVal(*I),
- RVal::GetSymbolValue(SymMgr, *I));
- }
-
- return St;
- }
+ StateTy getInitialState() { return StateMgr.getInitialState(); }
bool isUninitControlFlow(const NodeTy* N) const {
return N->isSink() && UninitBranches.count(const_cast<NodeTy*>(N)) != 0;
return N->isSink() && UninitDeref.count(const_cast<NodeTy*>(N)) != 0;
}
+ bool isBadDivide(const NodeTy* N) const {
+ return N->isSink() && BadDivides.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
typedef BadDerefTy::iterator null_iterator;
null_iterator null_begin() { return ExplicitNullDeref.begin(); }
null_iterator null_end() { return ExplicitNullDeref.end(); }
return StateMgr.GetLVal(St, Ex);
}
+ StateTy Symbolicate(StateTy St, VarDecl* VD) {
+ lval::DeclVal X(VD);
+
+ if (GetRVal(St, X).isUnknown()) {
+ return SetRVal(St, lval::DeclVal(VD), RVal::GetSymbolValue(SymMgr, VD));
+ }
+ else return St;
+ }
+
inline NonLVal MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLVal::MakeVal(ValMgr, X, Ex->getType(), Ex->getLocStart());
}
return !(*this == R);
}
- static RVal GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
+ static RVal GetSymbolValue(SymbolManager& SymMgr, VarDecl *D);
inline bool isUnknown() const {
return getRawKind() == UnknownKind;
class SymbolData {
public:
- enum Kind { UninitKind, ParmKind, ContentsOfKind };
+ enum Kind { UninitKind, ParmKind, GlobalKind, ContentsOfKind };
private:
uintptr_t Data;
return D->getKind() == ParmKind;
}
};
+
+class SymbolDataGlobalVar : public SymbolData {
+public:
+ SymbolDataGlobalVar(VarDecl* VD) : SymbolData(VD, GlobalKind) {}
+
+ VarDecl* getDecl() const { return (VarDecl*) getPtr(); }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymbolData* D) {
+ return D->getKind() == GlobalKind;
+ }
+};
class SymbolDataContentsOf : public SymbolData {
public:
SymbolManager();
~SymbolManager();
- SymbolID getSymbol(ParmVarDecl* D);
+ SymbolID getSymbol(VarDecl* D);
SymbolID getContentsOfSymbol(SymbolID sym);
inline const SymbolData& getSymbolData(SymbolID ID) const {