diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-11-16 07:52:17 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-11-16 07:52:17 +0000 |
commit | 9dc84c9455df2a77195147d0210c915dc1775a88 (patch) | |
tree | 17f323502c631bd4a851a4ad8f5470d170c3f42a /lib | |
parent | a437ad3ec5b407ede394d74e6f9f463fa3657dbe (diff) |
Handle member initializer in C++ ctor.
- Add a new Kind of ProgramPoint: PostInitializer.
- Still use GRStmtNodeBuilder. But special handling PostInitializer in
GRStmtNodeBuilder::GenerateAutoTransition().
- Someday we should clean up the interface of GRStmtNodeBuilder.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119335 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Checker/GRCXXExprEngine.cpp | 11 | ||||
-rw-r--r-- | lib/Checker/GRCoreEngine.cpp | 17 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 40 |
3 files changed, 54 insertions, 14 deletions
diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp index 890387632f..072c21e721 100644 --- a/lib/Checker/GRCXXExprEngine.cpp +++ b/lib/Checker/GRCXXExprEngine.cpp @@ -64,10 +64,10 @@ void GRExprEngine::EvalArguments(ConstExprIterator AI, ConstExprIterator AE, } } -const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D, +const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXRecordDecl *D, const StackFrameContext *SFC) { - Type *T = D->getParent()->getTypeForDecl(); - QualType PT = getContext().getPointerType(QualType(T,0)); + Type *T = D->getTypeForDecl(); + QualType PT = getContext().getPointerType(QualType(T, 0)); return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC); } @@ -121,7 +121,8 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, Pred->getLocationContext(), E, Builder->getBlock(), Builder->getIndex()); - const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC); + const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(), + SFC); CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext()); for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(), @@ -182,7 +183,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, MCE, Builder->getBlock(), Builder->getIndex()); - const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC); + const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC); CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext()); for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(), E = PreVisitChecks.end(); I != E; ++I) { diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp index 01d254c8f4..c77a0228e4 100644 --- a/lib/Checker/GRCoreEngine.cpp +++ b/lib/Checker/GRCoreEngine.cpp @@ -233,9 +233,9 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps, break; default: - assert(isa<PostStmt>(Node->getLocation())); - HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(), - WU.getIndex(), Node); + assert(isa<PostStmt>(Node->getLocation()) || + isa<PostInitializer>(Node->getLocation())); + HandlePostStmt(WU.getBlock(), WU.getIndex(), Node); break; } } @@ -413,9 +413,8 @@ void GRCoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term, ProcessBranch(Cond, Term, Builder); } -void GRCoreEngine::HandlePostStmt(const PostStmt& L, const CFGBlock* B, - unsigned StmtIdx, ExplodedNode* Pred) { - +void GRCoreEngine::HandlePostStmt(const CFGBlock* B, unsigned StmtIdx, + ExplodedNode* Pred) { assert (!B->empty()); if (StmtIdx == B->size()) @@ -473,6 +472,12 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) { return; } + // Do not create extra nodes. Move to the next CFG element. + if (isa<PostInitializer>(N->getLocation())) { + Eng.WList->Enqueue(N, &B, Idx+1); + return; + } + PostStmt Loc(getStmt(), N->getLocationContext()); if (Loc == N->getLocation()) { diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 017a6959cc..acb67d63dc 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -327,7 +327,7 @@ GRExprEngine::GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf) SymMgr(StateMgr.getSymbolManager()), ValMgr(StateMgr.getValueManager()), SVator(ValMgr.getSValuator()), - CurrentStmt(NULL), + EntryNode(NULL), CurrentStmt(NULL), NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), RaiseSel(GetNullarySelector("raise", getContext())), BR(mgr, *this), TF(tf) { @@ -679,8 +679,41 @@ void GRExprEngine::ProcessStmt(const CFGStmt S, GRStmtNodeBuilder& builder) { Builder = NULL; } -void GRExprEngine::ProcessInitializer(const CFGInitializer I, +void GRExprEngine::ProcessInitializer(const CFGInitializer Init, GRStmtNodeBuilder &builder) { + // We don't set EntryNode and CurrentStmt. And we don't clean up state. + const CXXBaseOrMemberInitializer *BMI = Init.getInitializer(); + + ExplodedNode *Pred = builder.getBasePredecessor(); + const LocationContext *LC = Pred->getLocationContext(); + + if (BMI->isMemberInitializer()) { + ExplodedNodeSet Dst; + + // Evaluate the initializer. + Visit(BMI->getInit(), Pred, Dst); + + for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){ + ExplodedNode *Pred = *I; + const GRState *state = Pred->getState(); + + const FieldDecl *FD = BMI->getMember(); + const RecordDecl *RD = FD->getParent(); + const CXXThisRegion *ThisR = getCXXThisRegion(cast<CXXRecordDecl>(RD), + cast<StackFrameContext>(LC)); + + SVal ThisV = state->getSVal(ThisR); + SVal FieldLoc = state->getLValue(FD, ThisV); + SVal InitVal = state->getSVal(BMI->getInit()); + state = state->bindLoc(FieldLoc, InitVal); + + // Use a custom node building process. + PostInitializer PP(BMI, LC); + // Builder automatically add the generated node to the deferred set, + // which are processed in the builder's dtor. + builder.generateNode(PP, state, Pred); + } + } } void GRExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, @@ -1566,7 +1599,8 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) { // Bind the constructed object value to CXXConstructExpr. if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { - const CXXThisRegion *ThisR = getCXXThisRegion(CCE->getConstructor(),LocCtx); + const CXXThisRegion *ThisR = + getCXXThisRegion(CCE->getConstructor()->getParent(), LocCtx); // We might not have 'this' region in the binding if we didn't inline // the ctor call. SVal ThisV = state->getSVal(ThisR); |