diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-11-24 13:08:51 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-11-24 13:08:51 +0000 |
commit | d706434b0231c76fd9acf30060646a7aa8f69aef (patch) | |
tree | 84ea6bde3550736b956941dfe3ed50fb377cf1ee /lib/Checker | |
parent | 13cf5e2e223ebfc8ec0459913b2fc9ec1e5fa760 (diff) |
Let StackFrameContext represent if the call expr is evaluated as lvalue.
This is required for supporting const reference to temporary objects.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120093 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Checker')
-rw-r--r-- | lib/Checker/AggExprVisitor.cpp | 2 | ||||
-rw-r--r-- | lib/Checker/Environment.cpp | 13 | ||||
-rw-r--r-- | lib/Checker/GRCXXExprEngine.cpp | 8 | ||||
-rw-r--r-- | lib/Checker/GRCoreEngine.cpp | 2 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 35 |
5 files changed, 45 insertions, 15 deletions
diff --git a/lib/Checker/AggExprVisitor.cpp b/lib/Checker/AggExprVisitor.cpp index f31bcec73a..9244275343 100644 --- a/lib/Checker/AggExprVisitor.cpp +++ b/lib/Checker/AggExprVisitor.cpp @@ -53,7 +53,7 @@ void AggExprVisitor::VisitCastExpr(CastExpr *E) { } void AggExprVisitor::VisitCXXConstructExpr(CXXConstructExpr *E) { - Eng.VisitCXXConstructExpr(E, Dest, Pred, DstSet); + Eng.VisitCXXConstructExpr(E, Dest, Pred, DstSet, false); } void GRExprEngine::VisitAggExpr(const Expr *E, const MemRegion *Dest, diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp index 914070e030..0bbe40dc1a 100644 --- a/lib/Checker/Environment.cpp +++ b/lib/Checker/Environment.cpp @@ -65,11 +65,22 @@ SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const { if (CT->isVoidType()) return UnknownVal(); + if (C->getCastKind() == CK_NoOp) { + E = C->getSubExpr(); + continue; + } break; } - // Handle all other Stmt* using a lookup. + case Stmt::CXXExprWithTemporariesClass: + E = cast<CXXExprWithTemporaries>(E)->getSubExpr(); + continue; + case Stmt::CXXBindTemporaryExprClass: + E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); + continue; + + // Handle all other Stmt* using a lookup. default: break; }; diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp index e9939af1eb..4a0fdc66ed 100644 --- a/lib/Checker/GRCXXExprEngine.cpp +++ b/lib/Checker/GRCXXExprEngine.cpp @@ -100,7 +100,7 @@ void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred, void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest, ExplodedNode *Pred, - ExplodedNodeSet &Dst) { + ExplodedNodeSet &Dst, bool asLValue) { if (!Dest) Dest = ValMgr.getRegionManager().getCXXObjectRegion(E, Pred->getLocationContext()); @@ -125,7 +125,7 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, // The callee stack frame context used to create the 'this' parameter region. const StackFrameContext *SFC = AMgr.getStackFrame(CD, Pred->getLocationContext(), - E, Builder->getBlock(), Builder->getIndex()); + E, asLValue, Builder->getBlock(), Builder->getIndex()); const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(), SFC); @@ -153,7 +153,7 @@ void GRExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, // Create the context for 'this' region. const StackFrameContext *SFC = AMgr.getStackFrame(DD, Pred->getLocationContext(), - S, Builder->getBlock(), + S, false, Builder->getBlock(), Builder->getIndex()); const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); @@ -239,7 +239,7 @@ void GRExprEngine::EvalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD, const StackFrameContext *SFC = AMgr.getStackFrame(MD, Pred->getLocationContext(), - MCE, + MCE, false, Builder->getBlock(), Builder->getIndex()); const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC); diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp index 270985f416..a676e6ca26 100644 --- a/lib/Checker/GRCoreEngine.cpp +++ b/lib/Checker/GRCoreEngine.cpp @@ -758,7 +758,7 @@ void GRCallEnterNodeBuilder::GenerateNode(const GRState *state) { const StackFrameContext *OldLocCtx = CalleeCtx; const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx, OldLocCtx->getParent(), - OldLocCtx->getCallSite(), + OldLocCtx->getCallSite(), false, OldLocCtx->getCallSiteBlock(), OldLocCtx->getIndex()); diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index f0aa38b07c..2181b705f7 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -918,7 +918,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, const CXXConstructExpr *C = cast<CXXConstructExpr>(S); // For block-level CXXConstructExpr, we don't have a destination region. // Let VisitCXXConstructExpr() create one. - VisitCXXConstructExpr(C, 0, Pred, Dst); + VisitCXXConstructExpr(C, 0, Pred, Dst, false); break; } @@ -1117,7 +1117,6 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred, switch (Ex->getStmtClass()) { // C++ stuff we don't support yet. - case Stmt::CXXExprWithTemporariesClass: case Stmt::CXXMemberCallExprClass: case Stmt::CXXScalarValueInitExprClass: { SaveAndRestore<bool> OldSink(Builder->BuildSinks); @@ -1147,6 +1146,24 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred, break; } + case Stmt::CXXExprWithTemporariesClass: { + const CXXExprWithTemporaries *expr = cast<CXXExprWithTemporaries>(Ex); + VisitLValue(expr->getSubExpr(), Pred, Dst); + break; + } + + case Stmt::CXXBindTemporaryExprClass: { + const CXXBindTemporaryExpr *expr = cast<CXXBindTemporaryExpr>(Ex); + VisitLValue(expr->getSubExpr(), Pred, Dst); + break; + } + + case Stmt::CXXTemporaryObjectExprClass: { + const CXXTemporaryObjectExpr *expr = cast<CXXTemporaryObjectExpr>(Ex); + VisitCXXTemporaryObjectExpr(expr, Pred, Dst, true); + break; + } + case Stmt::CompoundLiteralExprClass: VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst, true); return; @@ -1643,11 +1660,13 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) { if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { const CXXThisRegion *ThisR = getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); - // We might not have 'this' region in the binding if we didn't inline - // the ctor call. + SVal ThisV = state->getSVal(ThisR); - loc::MemRegionVal *V = dyn_cast<loc::MemRegionVal>(&ThisV); - if (V) { + + if (calleeCtx->evalAsLValue()) { + state = state->BindExpr(CCE, ThisV); + } else { + loc::MemRegionVal *V = cast<loc::MemRegionVal>(&ThisV); SVal ObjVal = state->getSVal(V->getRegion()); assert(isa<nonloc::LazyCompoundVal>(ObjVal)); state = state->BindExpr(CCE, ObjVal); @@ -2073,7 +2092,7 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, const StackFrameContext *stackFrame = AMgr.getStackFrame(AMgr.getAnalysisContext(FD), Pred->getLocationContext(), - CE, Builder->getBlock(), Builder->getIndex()); + CE, false, Builder->getBlock(), Builder->getIndex()); // Now we have the definition of the callee, create a CallEnter node. CallEnter Loc(CE, stackFrame, Pred->getLocationContext()); @@ -2089,7 +2108,7 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, return false; const StackFrameContext *stackFrame = AMgr.getStackFrame(C, Pred->getLocationContext(), - CE, Builder->getBlock(), Builder->getIndex()); + CE, false, Builder->getBlock(), Builder->getIndex()); CallEnter Loc(CE, stackFrame, Pred->getLocationContext()); ExplodedNode *N = Builder->generateNode(Loc, state, Pred); Dst.Add(N); |