From: Zhongxing Xu Date: Tue, 20 Apr 2010 03:37:34 +0000 (+0000) Subject: Improve handling of CXXNewExpr. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b17b1b3cc2b0d4d3b263b9384571bbc7f3995771;p=clang Improve handling of CXXNewExpr. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101862 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 4d8618f5ec..7e8f753a83 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -375,6 +375,11 @@ public: const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD, 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 /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) /// with those assumptions. diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp index d5f545a397..67c478b86f 100644 --- a/lib/Checker/GRCXXExprEngine.cpp +++ b/lib/Checker/GRCXXExprEngine.cpp @@ -17,6 +17,37 @@ using namespace clang; +void GRExprEngine::EvalArguments(ExprIterator AI, ExprIterator AE, + const FunctionProtoType *FnType, + ExplodedNode *Pred, ExplodedNodeSet &Dst) { + llvm::SmallVector 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 StackFrameContext *SFC) { Type *T = D->getParent()->getTypeForDecl(); @@ -212,14 +243,38 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred, const ElementRegion *EleReg = 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(); + ExplodedNodeSet ArgsEvaluated; + EvalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), + FnType, Pred, ArgsEvaluated); - Store store = state->getStore(); - StoreManager::InvalidatedSymbols IS; - store = getStoreManager().InvalidateRegion(store, EleReg, CNE, Count, &IS); - state = state->makeWithStore(store); - state = state->BindExpr(CNE, loc::MemRegionVal(EleReg)); - MakeNode(Dst, CNE, Pred, state); + // Initialize the object region and bind the 'new' expression. + for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(), + E = ArgsEvaluated.end(); I != E; ++I) { + const GRState *state = GetState(*I); + + 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); + } }