From: Zhongxing Xu Date: Wed, 24 Nov 2010 13:08:51 +0000 (+0000) Subject: Let StackFrameContext represent if the call expr is evaluated as lvalue. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d706434b0231c76fd9acf30060646a7aa8f69aef;p=clang 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 --- diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 0a61f440da..a941f7fe57 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -198,8 +198,9 @@ public: }; class StackFrameContext : public LocationContext { - // The callsite where this stack frame is established. - const Stmt *CallSite; + // The callsite where this stack frame is established. The int bit indicates + // whether the call expr should return an l-value when it has reference type. + llvm::PointerIntPair CallSite; // The parent block of the callsite. const CFGBlock *Block; @@ -209,14 +210,17 @@ class StackFrameContext : public LocationContext { friend class LocationContextManager; StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s, const CFGBlock *blk, unsigned idx) - : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), - Index(idx) {} + const Stmt *s, bool asLValue, const CFGBlock *blk, + unsigned idx) + : LocationContext(StackFrame, ctx, parent), CallSite(s, asLValue), + Block(blk), Index(idx) {} public: ~StackFrameContext() {} - const Stmt *getCallSite() const { return CallSite; } + const Stmt *getCallSite() const { return CallSite.getPointer(); } + + bool evalAsLValue() const { return CallSite.getInt(); } const CFGBlock *getCallSiteBlock() const { return Block; } @@ -226,8 +230,9 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, const LocationContext *parent, const Stmt *s, - const CFGBlock *blk, unsigned idx) { + bool asLValue, const CFGBlock *blk, unsigned idx) { ProfileCommon(ID, StackFrame, ctx, parent, s); + ID.AddBoolean(asLValue); ID.AddPointer(blk); ID.AddInteger(idx); } @@ -295,8 +300,8 @@ public: const StackFrameContext *getStackFrame(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s, const CFGBlock *blk, - unsigned idx); + const Stmt *s, bool asLValue, + const CFGBlock *blk, unsigned idx); const ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent, diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h index 79d9903890..ce33269da0 100644 --- a/include/clang/Checker/PathSensitive/AnalysisManager.h +++ b/include/clang/Checker/PathSensitive/AnalysisManager.h @@ -178,23 +178,24 @@ public: const StackFrameContext *getStackFrame(AnalysisContext *Ctx, LocationContext const *Parent, - Stmt const *S, const CFGBlock *Blk, - unsigned Idx) { - return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx); + const Stmt *S, bool asLValue, + const CFGBlock *Blk, unsigned Idx) { + return LocCtxMgr.getStackFrame(Ctx, Parent, S, asLValue, Blk, Idx); } // Get the top level stack frame. const StackFrameContext *getStackFrame(Decl const *D, idx::TranslationUnit *TU) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0); + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0, 0); } // Get a stack frame with parent. - StackFrameContext const *getStackFrame(Decl const *D, + StackFrameContext const *getStackFrame(const Decl *D, LocationContext const *Parent, - Stmt const *S, const CFGBlock *Blk, - unsigned Idx) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx); + const Stmt *S, bool asLValue, + const CFGBlock *Blk, unsigned Idx) { + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, asLValue, + Blk,Idx); } }; diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 04fce44480..4e97b8ee2e 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -424,9 +424,16 @@ public: void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet & Dst); - + + void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, + ExplodedNode *Pred, ExplodedNodeSet &Dst, + bool asLValue) { + VisitCXXConstructExpr(expr, 0, Pred, Dst, asLValue); + } + void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest, - ExplodedNode *Pred, ExplodedNodeSet &Dst); + ExplodedNode *Pred, ExplodedNodeSet &Dst, + bool asLValue); void VisitCXXDestructor(const CXXDestructorDecl *DD, const MemRegion *Dest, const Stmt *S, diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 68c5e158f3..5307074dce 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -152,7 +152,8 @@ void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID, } void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index); + Profile(ID, getAnalysisContext(), getParent(), CallSite.getPointer(), + CallSite.getInt(), Block, Index); } void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) { @@ -188,15 +189,15 @@ LocationContextManager::getLocationContext(AnalysisContext *ctx, const StackFrameContext* LocationContextManager::getStackFrame(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s, const CFGBlock *blk, - unsigned idx) { + const Stmt *s, bool asLValue, + const CFGBlock *blk, unsigned idx) { llvm::FoldingSetNodeID ID; - StackFrameContext::Profile(ID, ctx, parent, s, blk, idx); + StackFrameContext::Profile(ID, ctx, parent, s, asLValue, blk, idx); void *InsertPos; StackFrameContext *L = cast_or_null(Contexts.FindNodeOrInsertPos(ID, InsertPos)); if (!L) { - L = new StackFrameContext(ctx, parent, s, blk, idx); + L = new StackFrameContext(ctx, parent, s, asLValue, blk, idx); Contexts.InsertNode(L, InsertPos); } return L; 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(E)->getSubExpr(); + continue; + case Stmt::CXXBindTemporaryExprClass: + E = cast(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(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 OldSink(Builder->BuildSinks); @@ -1147,6 +1146,24 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred, break; } + case Stmt::CXXExprWithTemporariesClass: { + const CXXExprWithTemporaries *expr = cast(Ex); + VisitLValue(expr->getSubExpr(), Pred, Dst); + break; + } + + case Stmt::CXXBindTemporaryExprClass: { + const CXXBindTemporaryExpr *expr = cast(Ex); + VisitLValue(expr->getSubExpr(), Pred, Dst); + break; + } + + case Stmt::CXXTemporaryObjectExprClass: { + const CXXTemporaryObjectExpr *expr = cast(Ex); + VisitCXXTemporaryObjectExpr(expr, Pred, Dst, true); + break; + } + case Stmt::CompoundLiteralExprClass: VisitCompoundLiteralExpr(cast(Ex), Pred, Dst, true); return; @@ -1643,11 +1660,13 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) { if (const CXXConstructExpr *CCE = dyn_cast(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(&ThisV); - if (V) { + + if (calleeCtx->evalAsLValue()) { + state = state->BindExpr(CCE, ThisV); + } else { + loc::MemRegionVal *V = cast(&ThisV); SVal ObjVal = state->getSVal(V->getRegion()); assert(isa(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);