Use a worklist in GRExprEngine::VisitInitListExpr to process subexpressions.

llvm-svn: 58440
This commit is contained in:
Ted Kremenek 2008-10-30 17:47:32 +00:00
parent a2ace41aa3
commit f68bf63611
1 changed files with 55 additions and 26 deletions

View File

@ -1619,6 +1619,22 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {
} }
} }
namespace {
// This class is used by VisitInitListExpr as an item in a worklist
// for processing the values contained in an InitListExpr.
class VISIBILITY_HIDDEN InitListWLItem {
public:
llvm::ImmutableList<SVal> Vals;
GRExprEngine::NodeTy* N;
InitListExpr::reverse_iterator Itr;
InitListWLItem(GRExprEngine::NodeTy* n, llvm::ImmutableList<SVal> vals,
InitListExpr::reverse_iterator itr)
: Vals(vals), N(n), Itr(itr) {}
};
}
void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred, void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
NodeSet& Dst) { NodeSet& Dst) {
const GRState* state = GetState(Pred); const GRState* state = GetState(Pred);
@ -1627,36 +1643,49 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
unsigned NumInitElements = E->getNumInits(); unsigned NumInitElements = E->getNumInits();
llvm::SmallVector<SVal, 10> InitVals;
InitVals.reserve(NumInitElements);
if (T->isArrayType() || T->isStructureType()) { if (T->isArrayType() || T->isStructureType()) {
for (unsigned i = 0; i < NumInitElements; ++i) {
Expr* Init = E->getInit(i);
llvm::SmallVector<InitListWLItem, 10> WorkList;
WorkList.reserve(NumInitElements);
WorkList.push_back(InitListWLItem(Pred, getBasicVals().getEmptySValList(),
E->rbegin()));
InitListExpr::reverse_iterator ItrEnd = E->rend();
while (!WorkList.empty()) {
InitListWLItem X = WorkList.back();
WorkList.pop_back();
NodeSet Tmp; NodeSet Tmp;
Visit(Init, Pred, Tmp); Visit(*X.Itr, X.N, Tmp);
// FIXME: Use worklist to allow state splitting. InitListExpr::reverse_iterator NewItr = X.Itr + 1;
assert(Tmp.size() == 1);
// Get the new intermediate node and its state. for (NodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
Pred = *Tmp.begin(); // Get the last initializer value.
state = GetState(Pred); state = GetState(*NI);
SVal InitV = GetSVal(state, cast<Expr>(*X.Itr));
SVal InitV = GetSVal(state, Init); // Construct the new list of values by prepending the new value to
InitVals.push_back(InitV); // the already constructed list.
} llvm::ImmutableList<SVal> NewVals =
getBasicVals().consVals(InitV, X.Vals);
// Now we have a vector holding all init values. Make CompoundSValData. if (NewItr == ItrEnd) {
SVal V = NonLoc::MakeCompoundVal(T, &InitVals[0], NumInitElements, // Now we have a list holding all init values. Make CompoundSValData.
StateMgr.getBasicVals()); SVal V = NonLoc::MakeCompoundVal(T, NewVals, getBasicVals());
// Make final state and node. // Make final state and node.
state = BindExpr(state, E, V); MakeNode(Dst, E, Pred, BindExpr(state, E, V));
}
MakeNode(Dst, E, Pred, state); else {
return; // Still some initializer values to go. Push them onto the worklist.
WorkList.push_back(InitListWLItem(*NI, NewVals, NewItr));
}
}
}
} }
if (Loc::IsLocType(T) || T->isIntegerType()) { if (Loc::IsLocType(T) || T->isIntegerType()) {