forked from OSchip/llvm-project
Let StackFrameContext represent if the call expr is evaluated as lvalue.
This is required for supporting const reference to temporary objects. llvm-svn: 120093
This commit is contained in:
parent
e0a1d2b32c
commit
a1a9ba11b7
|
|
@ -198,8 +198,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class StackFrameContext : public LocationContext {
|
class StackFrameContext : public LocationContext {
|
||||||
// The callsite where this stack frame is established.
|
// The callsite where this stack frame is established. The int bit indicates
|
||||||
const Stmt *CallSite;
|
// whether the call expr should return an l-value when it has reference type.
|
||||||
|
llvm::PointerIntPair<const Stmt *, 1> CallSite;
|
||||||
|
|
||||||
// The parent block of the callsite.
|
// The parent block of the callsite.
|
||||||
const CFGBlock *Block;
|
const CFGBlock *Block;
|
||||||
|
|
@ -209,14 +210,17 @@ class StackFrameContext : public LocationContext {
|
||||||
|
|
||||||
friend class LocationContextManager;
|
friend class LocationContextManager;
|
||||||
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
|
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||||
const Stmt *s, const CFGBlock *blk, unsigned idx)
|
const Stmt *s, bool asLValue, const CFGBlock *blk,
|
||||||
: LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
|
unsigned idx)
|
||||||
Index(idx) {}
|
: LocationContext(StackFrame, ctx, parent), CallSite(s, asLValue),
|
||||||
|
Block(blk), Index(idx) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~StackFrameContext() {}
|
~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; }
|
const CFGBlock *getCallSiteBlock() const { return Block; }
|
||||||
|
|
||||||
|
|
@ -226,8 +230,9 @@ public:
|
||||||
|
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||||
const LocationContext *parent, const Stmt *s,
|
const LocationContext *parent, const Stmt *s,
|
||||||
const CFGBlock *blk, unsigned idx) {
|
bool asLValue, const CFGBlock *blk, unsigned idx) {
|
||||||
ProfileCommon(ID, StackFrame, ctx, parent, s);
|
ProfileCommon(ID, StackFrame, ctx, parent, s);
|
||||||
|
ID.AddBoolean(asLValue);
|
||||||
ID.AddPointer(blk);
|
ID.AddPointer(blk);
|
||||||
ID.AddInteger(idx);
|
ID.AddInteger(idx);
|
||||||
}
|
}
|
||||||
|
|
@ -295,8 +300,8 @@ public:
|
||||||
|
|
||||||
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
|
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
|
||||||
const LocationContext *parent,
|
const LocationContext *parent,
|
||||||
const Stmt *s, const CFGBlock *blk,
|
const Stmt *s, bool asLValue,
|
||||||
unsigned idx);
|
const CFGBlock *blk, unsigned idx);
|
||||||
|
|
||||||
const ScopeContext *getScope(AnalysisContext *ctx,
|
const ScopeContext *getScope(AnalysisContext *ctx,
|
||||||
const LocationContext *parent,
|
const LocationContext *parent,
|
||||||
|
|
|
||||||
|
|
@ -178,23 +178,24 @@ public:
|
||||||
|
|
||||||
const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
|
const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
|
||||||
LocationContext const *Parent,
|
LocationContext const *Parent,
|
||||||
Stmt const *S, const CFGBlock *Blk,
|
const Stmt *S, bool asLValue,
|
||||||
unsigned Idx) {
|
const CFGBlock *Blk, unsigned Idx) {
|
||||||
return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
|
return LocCtxMgr.getStackFrame(Ctx, Parent, S, asLValue, Blk, Idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the top level stack frame.
|
// Get the top level stack frame.
|
||||||
const StackFrameContext *getStackFrame(Decl const *D,
|
const StackFrameContext *getStackFrame(Decl const *D,
|
||||||
idx::TranslationUnit *TU) {
|
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.
|
// Get a stack frame with parent.
|
||||||
StackFrameContext const *getStackFrame(Decl const *D,
|
StackFrameContext const *getStackFrame(const Decl *D,
|
||||||
LocationContext const *Parent,
|
LocationContext const *Parent,
|
||||||
Stmt const *S, const CFGBlock *Blk,
|
const Stmt *S, bool asLValue,
|
||||||
unsigned Idx) {
|
const CFGBlock *Blk, unsigned Idx) {
|
||||||
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx);
|
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, asLValue,
|
||||||
|
Blk,Idx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -425,8 +425,15 @@ public:
|
||||||
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
|
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
|
||||||
ExplodedNodeSet & Dst);
|
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,
|
void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest,
|
||||||
ExplodedNode *Pred, ExplodedNodeSet &Dst);
|
ExplodedNode *Pred, ExplodedNodeSet &Dst,
|
||||||
|
bool asLValue);
|
||||||
|
|
||||||
void VisitCXXDestructor(const CXXDestructorDecl *DD,
|
void VisitCXXDestructor(const CXXDestructorDecl *DD,
|
||||||
const MemRegion *Dest, const Stmt *S,
|
const MemRegion *Dest, const Stmt *S,
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,8 @@ void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackFrameContext::Profile(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) {
|
void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
|
|
@ -188,15 +189,15 @@ LocationContextManager::getLocationContext(AnalysisContext *ctx,
|
||||||
const StackFrameContext*
|
const StackFrameContext*
|
||||||
LocationContextManager::getStackFrame(AnalysisContext *ctx,
|
LocationContextManager::getStackFrame(AnalysisContext *ctx,
|
||||||
const LocationContext *parent,
|
const LocationContext *parent,
|
||||||
const Stmt *s, const CFGBlock *blk,
|
const Stmt *s, bool asLValue,
|
||||||
unsigned idx) {
|
const CFGBlock *blk, unsigned idx) {
|
||||||
llvm::FoldingSetNodeID ID;
|
llvm::FoldingSetNodeID ID;
|
||||||
StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
|
StackFrameContext::Profile(ID, ctx, parent, s, asLValue, blk, idx);
|
||||||
void *InsertPos;
|
void *InsertPos;
|
||||||
StackFrameContext *L =
|
StackFrameContext *L =
|
||||||
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
|
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
|
||||||
if (!L) {
|
if (!L) {
|
||||||
L = new StackFrameContext(ctx, parent, s, blk, idx);
|
L = new StackFrameContext(ctx, parent, s, asLValue, blk, idx);
|
||||||
Contexts.InsertNode(L, InsertPos);
|
Contexts.InsertNode(L, InsertPos);
|
||||||
}
|
}
|
||||||
return L;
|
return L;
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ void AggExprVisitor::VisitCastExpr(CastExpr *E) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AggExprVisitor::VisitCXXConstructExpr(CXXConstructExpr *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,
|
void GRExprEngine::VisitAggExpr(const Expr *E, const MemRegion *Dest,
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,22 @@ SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
|
||||||
if (CT->isVoidType())
|
if (CT->isVoidType())
|
||||||
return UnknownVal();
|
return UnknownVal();
|
||||||
|
|
||||||
|
if (C->getCastKind() == CK_NoOp) {
|
||||||
|
E = C->getSubExpr();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
|
||||||
void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||||
const MemRegion *Dest,
|
const MemRegion *Dest,
|
||||||
ExplodedNode *Pred,
|
ExplodedNode *Pred,
|
||||||
ExplodedNodeSet &Dst) {
|
ExplodedNodeSet &Dst, bool asLValue) {
|
||||||
if (!Dest)
|
if (!Dest)
|
||||||
Dest = ValMgr.getRegionManager().getCXXObjectRegion(E,
|
Dest = ValMgr.getRegionManager().getCXXObjectRegion(E,
|
||||||
Pred->getLocationContext());
|
Pred->getLocationContext());
|
||||||
|
|
@ -125,7 +125,7 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||||
// The callee stack frame context used to create the 'this' parameter region.
|
// The callee stack frame context used to create the 'this' parameter region.
|
||||||
const StackFrameContext *SFC = AMgr.getStackFrame(CD,
|
const StackFrameContext *SFC = AMgr.getStackFrame(CD,
|
||||||
Pred->getLocationContext(),
|
Pred->getLocationContext(),
|
||||||
E, Builder->getBlock(), Builder->getIndex());
|
E, asLValue, Builder->getBlock(), Builder->getIndex());
|
||||||
|
|
||||||
const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
|
const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
|
||||||
SFC);
|
SFC);
|
||||||
|
|
@ -153,7 +153,7 @@ void GRExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
|
||||||
// Create the context for 'this' region.
|
// Create the context for 'this' region.
|
||||||
const StackFrameContext *SFC = AMgr.getStackFrame(DD,
|
const StackFrameContext *SFC = AMgr.getStackFrame(DD,
|
||||||
Pred->getLocationContext(),
|
Pred->getLocationContext(),
|
||||||
S, Builder->getBlock(),
|
S, false, Builder->getBlock(),
|
||||||
Builder->getIndex());
|
Builder->getIndex());
|
||||||
|
|
||||||
const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
|
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,
|
const StackFrameContext *SFC = AMgr.getStackFrame(MD,
|
||||||
Pred->getLocationContext(),
|
Pred->getLocationContext(),
|
||||||
MCE,
|
MCE, false,
|
||||||
Builder->getBlock(),
|
Builder->getBlock(),
|
||||||
Builder->getIndex());
|
Builder->getIndex());
|
||||||
const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC);
|
const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC);
|
||||||
|
|
|
||||||
|
|
@ -758,7 +758,7 @@ void GRCallEnterNodeBuilder::GenerateNode(const GRState *state) {
|
||||||
const StackFrameContext *OldLocCtx = CalleeCtx;
|
const StackFrameContext *OldLocCtx = CalleeCtx;
|
||||||
const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
|
const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
|
||||||
OldLocCtx->getParent(),
|
OldLocCtx->getParent(),
|
||||||
OldLocCtx->getCallSite(),
|
OldLocCtx->getCallSite(), false,
|
||||||
OldLocCtx->getCallSiteBlock(),
|
OldLocCtx->getCallSiteBlock(),
|
||||||
OldLocCtx->getIndex());
|
OldLocCtx->getIndex());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -918,7 +918,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
|
||||||
const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
|
const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
|
||||||
// For block-level CXXConstructExpr, we don't have a destination region.
|
// For block-level CXXConstructExpr, we don't have a destination region.
|
||||||
// Let VisitCXXConstructExpr() create one.
|
// Let VisitCXXConstructExpr() create one.
|
||||||
VisitCXXConstructExpr(C, 0, Pred, Dst);
|
VisitCXXConstructExpr(C, 0, Pred, Dst, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1117,7 +1117,6 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
|
||||||
|
|
||||||
switch (Ex->getStmtClass()) {
|
switch (Ex->getStmtClass()) {
|
||||||
// C++ stuff we don't support yet.
|
// C++ stuff we don't support yet.
|
||||||
case Stmt::CXXExprWithTemporariesClass:
|
|
||||||
case Stmt::CXXMemberCallExprClass:
|
case Stmt::CXXMemberCallExprClass:
|
||||||
case Stmt::CXXScalarValueInitExprClass: {
|
case Stmt::CXXScalarValueInitExprClass: {
|
||||||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||||
|
|
@ -1147,6 +1146,24 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
|
||||||
break;
|
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:
|
case Stmt::CompoundLiteralExprClass:
|
||||||
VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst, true);
|
VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst, true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1643,11 +1660,13 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
|
||||||
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
|
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
|
||||||
const CXXThisRegion *ThisR =
|
const CXXThisRegion *ThisR =
|
||||||
getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
|
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);
|
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());
|
SVal ObjVal = state->getSVal(V->getRegion());
|
||||||
assert(isa<nonloc::LazyCompoundVal>(ObjVal));
|
assert(isa<nonloc::LazyCompoundVal>(ObjVal));
|
||||||
state = state->BindExpr(CCE, ObjVal);
|
state = state->BindExpr(CCE, ObjVal);
|
||||||
|
|
@ -2073,7 +2092,7 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
|
||||||
const StackFrameContext *stackFrame =
|
const StackFrameContext *stackFrame =
|
||||||
AMgr.getStackFrame(AMgr.getAnalysisContext(FD),
|
AMgr.getStackFrame(AMgr.getAnalysisContext(FD),
|
||||||
Pred->getLocationContext(),
|
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.
|
// Now we have the definition of the callee, create a CallEnter node.
|
||||||
CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
|
CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
|
||||||
|
|
||||||
|
|
@ -2089,7 +2108,7 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
|
||||||
return false;
|
return false;
|
||||||
const StackFrameContext *stackFrame =
|
const StackFrameContext *stackFrame =
|
||||||
AMgr.getStackFrame(C, Pred->getLocationContext(),
|
AMgr.getStackFrame(C, Pred->getLocationContext(),
|
||||||
CE, Builder->getBlock(), Builder->getIndex());
|
CE, false, Builder->getBlock(), Builder->getIndex());
|
||||||
CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
|
CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
|
||||||
ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
|
ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
|
||||||
Dst.Add(N);
|
Dst.Add(N);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue