Improve handling of CXXNewExpr.

llvm-svn: 101862
This commit is contained in:
Zhongxing Xu 2010-04-20 03:37:34 +00:00
parent 0f55a035cf
commit 40eb21a827
2 changed files with 67 additions and 7 deletions

View File

@ -375,6 +375,11 @@ public:
const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD, const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD,
const StackFrameContext *SFC); const StackFrameContext *SFC);
/// Evaluate arguments with a work list algorithm.
void EvalArguments(ExprIterator AI, ExprIterator AE,
const FunctionProtoType *FnType,
ExplodedNode *Pred, 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.

View File

@ -17,6 +17,37 @@
using namespace clang; using namespace clang;
void GRExprEngine::EvalArguments(ExprIterator AI, ExprIterator AE,
const FunctionProtoType *FnType,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
llvm::SmallVector<CallExprWLItem, 20> WorkList;
WorkList.reserve(AE - AI);
WorkList.push_back(CallExprWLItem(AI, Pred));
while (!WorkList.empty()) {
CallExprWLItem Item = WorkList.back();
WorkList.pop_back();
if (Item.I == AE) {
Dst.insert(Item.N);
continue;
}
ExplodedNodeSet Tmp;
const unsigned ParamIdx = Item.I - AI;
bool VisitAsLvalue = FnType? FnType->getArgType(ParamIdx)->isReferenceType()
: false;
if (VisitAsLvalue)
VisitLValue(*Item.I, Item.N, Tmp);
else
Visit(*Item.I, Item.N, Tmp);
++(Item.I);
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
WorkList.push_back(CallExprWLItem(Item.I, *NI));
}
}
const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D, const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
const StackFrameContext *SFC) { const StackFrameContext *SFC) {
Type *T = D->getParent()->getTypeForDecl(); Type *T = D->getParent()->getTypeForDecl();
@ -212,14 +243,38 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
const ElementRegion *EleReg = const ElementRegion *EleReg =
getStoreManager().GetElementZeroRegion(NewReg, ObjTy); getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
const GRState *state = Pred->getState(); // Evaluate constructor arguments.
const FunctionProtoType *FnType = NULL;
const CXXConstructorDecl *CD = CNE->getConstructor();
if (CD)
FnType = CD->getType()->getAs<FunctionProtoType>();
ExplodedNodeSet ArgsEvaluated;
EvalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
FnType, Pred, ArgsEvaluated);
Store store = state->getStore(); // Initialize the object region and bind the 'new' expression.
StoreManager::InvalidatedSymbols IS; for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
store = getStoreManager().InvalidateRegion(store, EleReg, CNE, Count, &IS); E = ArgsEvaluated.end(); I != E; ++I) {
state = state->makeWithStore(store); const GRState *state = GetState(*I);
state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
MakeNode(Dst, CNE, Pred, state); if (ObjTy->isRecordType()) {
Store store = state->getStore();
StoreManager::InvalidatedSymbols IS;
store = getStoreManager().InvalidateRegion(store, EleReg, CNE, Count, &IS);
state = state->makeWithStore(store);
} else {
if (CNE->hasInitializer()) {
SVal V = state->getSVal(*CNE->constructor_arg_begin());
state = state->bindLoc(loc::MemRegionVal(EleReg), V);
} else {
// Explicitly set to undefined, because currently we retrieve symbolic
// value from symbolic region.
state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
}
}
state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
MakeNode(Dst, CNE, Pred, state);
}
} }