Added lazy "symbolication" of parameter variables and global variables.
Added recording of divide-by-zero and divide-by-uninitialized nodes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47586 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp
index 6c363b0..fcbe4cc 100644
--- a/Analysis/GRExprEngine.cpp
+++ b/Analysis/GRExprEngine.cpp
@@ -396,6 +396,22 @@
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;
@@ -796,7 +812,20 @@
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;
}
@@ -857,20 +886,33 @@
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);
}
}
@@ -1003,8 +1045,19 @@
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;
@@ -1015,7 +1068,7 @@
if (DivZeroNode) {
DivZeroNode->markAsSink();
- DivZeroes.insert(DivZeroNode);
+ BadDivides.insert(DivZeroNode);
}
}
diff --git a/Analysis/RValues.cpp b/Analysis/RValues.cpp
index 178d794..bc6a75c 100644
--- a/Analysis/RValues.cpp
+++ b/Analysis/RValues.cpp
@@ -214,7 +214,7 @@
return nonlval::ConcreteInt(ValMgr.getTruthValue(b));
}
-RVal RVal::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) {
+RVal RVal::GetSymbolValue(SymbolManager& SymMgr, VarDecl* D) {
QualType T = D->getType();
diff --git a/Analysis/SymbolManager.cpp b/Analysis/SymbolManager.cpp
index ced5741..dd71dc9 100644
--- a/Analysis/SymbolManager.cpp
+++ b/Analysis/SymbolManager.cpp
@@ -16,17 +16,24 @@
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)];
@@ -45,6 +52,9 @@
case ParmKind:
return cast<SymbolDataParmVar>(this)->getDecl()->getType();
+
+ case GlobalKind:
+ return cast<SymbolDataGlobalVar>(this)->getDecl()->getType();
case ContentsOfKind: {
SymbolID x = cast<SymbolDataContentsOf>(this)->getSymbol();
diff --git a/Analysis/ValueState.cpp b/Analysis/ValueState.cpp
index 75f719a..03b2996 100644
--- a/Analysis/ValueState.cpp
+++ b/Analysis/ValueState.cpp
@@ -78,8 +78,16 @@
// 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.