本文整理汇总了C++中ExplodedNodeSet::Add方法的典型用法代码示例。如果您正苦于以下问题:C++ ExplodedNodeSet::Add方法的具体用法?C++ ExplodedNodeSet::Add怎么用?C++ ExplodedNodeSet::Add使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ExplodedNodeSet
的用法示例。
在下文中一共展示了ExplodedNodeSet::Add方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: VisitCXXConstructExpr
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
const MemRegion *Dest,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
if (!Dest)
Dest = svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
Pred->getLocationContext());
if (E->isElidable()) {
VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
// FIXME: this is here to force propogation if VisitAggExpr doesn't
if (Dst.empty())
Dst.Add(Pred);
return;
}
const CXXConstructorDecl *CD = E->getConstructor();
assert(CD);
if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
// FIXME: invalidate the object.
return;
// Evaluate other arguments.
ExplodedNodeSet argsEvaluated;
const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
// 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());
const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
SFC);
CallEnter Loc(E, SFC, Pred->getLocationContext());
for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
NE = argsEvaluated.end(); NI != NE; ++NI) {
const GRState *state = GetState(*NI);
// Setup 'this' region, so that the ctor is evaluated on the object pointed
// by 'Dest'.
state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
if (N)
Dst.Add(N);
}
}
示例2: ExecuteWorkListWithInitialState
void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
unsigned Steps,
const ProgramState *InitState,
ExplodedNodeSet &Dst) {
ExecuteWorkList(L, Steps, InitState);
for (SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
E = G->EndNodes.end(); I != E; ++I) {
Dst.Add(*I);
}
}
示例3: ExecuteWorkListWithInitialState
bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
unsigned Steps,
ProgramStateRef InitState,
ExplodedNodeSet &Dst) {
bool DidNotFinish = ExecuteWorkList(L, Steps, InitState);
for (ExplodedGraph::eop_iterator I = G->eop_begin(),
E = G->eop_end(); I != E; ++I) {
Dst.Add(*I);
}
return DidNotFinish;
}
示例4: VisitCXXMemberCallExpr
void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// Get the method type.
const FunctionProtoType *FnType =
MCE->getCallee()->getType()->getAs<FunctionProtoType>();
assert(FnType && "Method type not available");
// Evaluate explicit arguments with a worklist.
ExplodedNodeSet ArgsEvaluated;
EvalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, ArgsEvaluated);
// Evaluate the implicit object argument.
ExplodedNodeSet AllArgsEvaluated;
const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
if (!ME)
return;
Expr *ObjArgExpr = ME->getBase();
for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
E = ArgsEvaluated.end(); I != E; ++I) {
if (ME->isArrow())
Visit(ObjArgExpr, *I, AllArgsEvaluated);
else
VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
}
const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
assert(MD && "not a CXXMethodDecl?");
if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
// FIXME: conservative method call evaluation.
return;
const StackFrameContext *SFC = AMgr.getStackFrame(MD,
Pred->getLocationContext(),
MCE,
Builder->getBlock(),
Builder->getIndex());
const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
E = AllArgsEvaluated.end(); I != E; ++I) {
// Set up 'this' region.
const GRState *state = GetState(*I);
state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
ExplodedNode *N = Builder->generateNode(Loc, state, *I);
if (N)
Dst.Add(N);
}
}
示例5: VisitCXXCatchStmt
void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
const VarDecl *VD = CS->getExceptionDecl();
if (!VD) {
Dst.Add(Pred);
return;
}
const LocationContext *LCtx = Pred->getLocationContext();
SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(),
currBldrCtx->blockCount());
ProgramStateRef state = Pred->getState();
state = state->bindLoc(state->getLValue(VD, LCtx), V);
StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
Bldr.generateNode(CS, Pred, state);
}
示例6: VisitCXXConstructExpr
void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
if (E->isElidable()) {
VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
return;
}
const CXXConstructorDecl *CD = E->getConstructor();
assert(CD);
if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
// FIXME: invalidate the object.
return;
// Evaluate other arguments.
ExplodedNodeSet ArgsEvaluated;
const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
EvalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, ArgsEvaluated);
// 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());
const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
NE = ArgsEvaluated.end(); NI != NE; ++NI) {
const GRState *state = GetState(*NI);
// Setup 'this' region.
state = state->bindLoc(loc::MemRegionVal(ThisR), Dest);
ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
if (N)
Dst.Add(N);
}
}
示例7: removeDeadOnEndOfFunction
void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// Find the last statement in the function and the corresponding basic block.
const Stmt *LastSt = nullptr;
const CFGBlock *Blk = nullptr;
std::tie(LastSt, Blk) = getLastStmt(Pred);
if (!Blk || !LastSt) {
Dst.Add(Pred);
return;
}
// Here, we destroy the current location context. We use the current
// function's entire body as a diagnostic statement, with which the program
// point will be associated. However, we only want to use LastStmt as a
// reference for what to clean up if it's a ReturnStmt; otherwise, everything
// is dead.
SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
const LocationContext *LCtx = Pred->getLocationContext();
removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), LCtx,
LCtx->getAnalysisDeclContext()->getBody(),
ProgramPoint::PostStmtPurgeDeadSymbolsKind);
}
示例8: processCallExit
/// The call exit is simulated with a sequence of nodes, which occur between
/// CallExitBegin and CallExitEnd. The following operations occur between the
/// two program points:
/// 1. CallExitBegin (triggers the start of call exit sequence)
/// 2. Bind the return value
/// 3. Run Remove dead bindings to clean up the dead symbols from the callee.
/// 4. CallExitEnd (switch to the caller context)
/// 5. PostStmt<CallExpr>
void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// Step 1 CEBNode was generated before the call.
PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext());
const StackFrameContext *calleeCtx =
CEBNode->getLocationContext()->getCurrentStackFrame();
// The parent context might not be a stack frame, so make sure we
// look up the first enclosing stack frame.
const StackFrameContext *callerCtx =
calleeCtx->getParent()->getCurrentStackFrame();
const Stmt *CE = calleeCtx->getCallSite();
ProgramStateRef state = CEBNode->getState();
// Find the last statement in the function and the corresponding basic block.
const Stmt *LastSt = nullptr;
const CFGBlock *Blk = nullptr;
std::tie(LastSt, Blk) = getLastStmt(CEBNode);
// Generate a CallEvent /before/ cleaning the state, so that we can get the
// correct value for 'this' (if necessary).
CallEventManager &CEMgr = getStateManager().getCallEventManager();
CallEventRef<> Call = CEMgr.getCaller(calleeCtx, state);
// Step 2: generate node with bound return value: CEBNode -> BindedRetNode.
// If the callee returns an expression, bind its value to CallExpr.
if (CE) {
if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
const LocationContext *LCtx = CEBNode->getLocationContext();
SVal V = state->getSVal(RS, LCtx);
// Ensure that the return type matches the type of the returned Expr.
if (wasDifferentDeclUsedForInlining(Call, calleeCtx)) {
QualType ReturnedTy =
CallEvent::getDeclaredResultType(calleeCtx->getDecl());
if (!ReturnedTy.isNull()) {
if (const Expr *Ex = dyn_cast<Expr>(CE)) {
V = adjustReturnValue(V, Ex->getType(), ReturnedTy,
getStoreManager());
}
}
}
state = state->BindExpr(CE, callerCtx, V);
}
// Bind the constructed object value to CXXConstructExpr.
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
loc::MemRegionVal This =
svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
SVal ThisV = state->getSVal(This);
// If the constructed object is a temporary prvalue, get its bindings.
if (isTemporaryPRValue(CCE, ThisV))
ThisV = state->getSVal(ThisV.castAs<Loc>());
state = state->BindExpr(CCE, callerCtx, ThisV);
}
}
// Step 3: BindedRetNode -> CleanedNodes
// If we can find a statement and a block in the inlined function, run remove
// dead bindings before returning from the call. This is important to ensure
// that we report the issues such as leaks in the stack contexts in which
// they occurred.
ExplodedNodeSet CleanedNodes;
if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
static SimpleProgramPointTag retValBind("ExprEngine", "Bind Return Value");
PostStmt Loc(LastSt, calleeCtx, &retValBind);
bool isNew;
ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
BindedRetNode->addPredecessor(CEBNode, G);
if (!isNew)
return;
NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
currBldrCtx = &Ctx;
// Here, we call the Symbol Reaper with 0 statement and callee location
// context, telling it to clean up everything in the callee's context
// (and its children). We use the callee's function body as a diagnostic
// statement, with which the program point will be associated.
removeDead(BindedRetNode, CleanedNodes, nullptr, calleeCtx,
calleeCtx->getAnalysisDeclContext()->getBody(),
ProgramPoint::PostStmtPurgeDeadSymbolsKind);
currBldrCtx = nullptr;
} else {
CleanedNodes.Add(CEBNode);
}
for (ExplodedNodeSet::iterator I = CleanedNodes.begin(),
E = CleanedNodes.end(); I != E; ++I) {
//.........这里部分代码省略.........
示例9: VisitCXXConstructExpr
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNode *Pred,
ExplodedNodeSet &destNodes) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
const MemRegion *Target = nullptr;
// FIXME: Handle arrays, which run the same constructor for every element.
// For now, we just run the first constructor (which should still invalidate
// the entire array).
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
Target = getRegionForConstructedObject(CE, Pred, *this, currStmtIdx);
break;
}
case CXXConstructExpr::CK_VirtualBase:
// Make sure we are not calling virtual base class initializers twice.
// Only the most-derived object should initialize virtual base classes.
if (const Stmt *Outer = LCtx->getCurrentStackFrame()->getCallSite()) {
const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer);
if (OuterCtor) {
switch (OuterCtor->getConstructionKind()) {
case CXXConstructExpr::CK_NonVirtualBase:
case CXXConstructExpr::CK_VirtualBase:
// Bail out!
destNodes.Add(Pred);
return;
case CXXConstructExpr::CK_Complete:
case CXXConstructExpr::CK_Delegating:
break;
}
}
}
// FALLTHROUGH
case CXXConstructExpr::CK_NonVirtualBase:
case CXXConstructExpr::CK_Delegating: {
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
LCtx->getCurrentStackFrame());
SVal ThisVal = State->getSVal(ThisPtr);
if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) {
Target = ThisVal.getAsRegion();
} else {
// Cast to the base type.
bool IsVirtual =
(CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase);
SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(),
IsVirtual);
Target = BaseVal.getAsRegion();
}
break;
}
}
CallEventManager &CEMgr = getStateManager().getCallEventManager();
CallEventRef<CXXConstructorCall> Call =
CEMgr.getCXXConstructorCall(CE, Target, State, LCtx);
ExplodedNodeSet DstPreVisit;
getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
ExplodedNodeSet PreInitialized;
{
StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx);
if (CE->requiresZeroInitialization()) {
// Type of the zero doesn't matter.
SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy);
for (ExplodedNodeSet::iterator I = DstPreVisit.begin(),
E = DstPreVisit.end();
I != E; ++I) {
ProgramStateRef State = (*I)->getState();
// FIXME: Once we properly handle constructors in new-expressions, we'll
// need to invalidate the region before setting a default value, to make
// sure there aren't any lingering bindings around. This probably needs
// to happen regardless of whether or not the object is zero-initialized
// to handle random fields of a placement-initialized object picking up
// old bindings. We might only want to do it when we need to, though.
// FIXME: This isn't actually correct for arrays -- we need to zero-
// initialize the entire array, not just the first element -- but our
// handling of arrays everywhere else is weak as well, so this shouldn't
// actually make things worse. Placement new makes this tricky as well,
// since it's then possible to be initializing one part of a multi-
// dimensional array.
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal);
Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
ProgramPoint::PreStmtKind);
}
}
}
ExplodedNodeSet DstPreCall;
getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized,
*Call, *this);
ExplodedNodeSet DstEvaluated;
StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);
//.........这里部分代码省略.........
示例10: VisitCXXConstructExpr
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
const MemRegion *Dest,
ExplodedNode *Pred,
ExplodedNodeSet &destNodes) {
const CXXConstructorDecl *CD = E->getConstructor();
assert(CD);
#if 0
if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
// FIXME: invalidate the object.
return;
#endif
// Evaluate other arguments.
ExplodedNodeSet argsEvaluated;
const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
#if 0
// Is the constructor elidable?
if (E->isElidable()) {
VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
// FIXME: this is here to force propagation if VisitAggExpr doesn't
if (destNodes.empty())
destNodes.Add(Pred);
return;
}
#endif
// Perform the previsit of the constructor.
ExplodedNodeSet destPreVisit;
getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
*this);
// Evaluate the constructor. Currently we don't now allow checker-specific
// implementations of specific constructors (as we do with ordinary
// function calls. We can re-evaluate this in the future.
#if 0
// Inlining currently isn't fully implemented.
if (AMgr.shouldInlineCall()) {
if (!Dest)
Dest =
svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
Pred->getLocationContext());
// The callee stack frame context used to create the 'this'
// parameter region.
const StackFrameContext *SFC =
AMgr.getStackFrame(CD, Pred->getLocationContext(),
E, currentBuilderContext->getBlock(),
currentStmtIdx);
// Create the 'this' region.
const CXXThisRegion *ThisR =
getCXXThisRegion(E->getConstructor()->getParent(), SFC);
CallEnter Loc(E, SFC, Pred->getLocationContext());
StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext);
for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
NE = argsEvaluated.end(); NI != NE; ++NI) {
const ProgramState *state = (*NI)->getState();
// Setup 'this' region, so that the ctor is evaluated on the object pointed
// by 'Dest'.
state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
Bldr.generateNode(Loc, *NI, state);
}
}
#endif
// Default semantics: invalidate all regions passed as arguments.
ExplodedNodeSet destCall;
{
StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext);
for (ExplodedNodeSet::iterator
i = destPreVisit.begin(), e = destPreVisit.end();
i != e; ++i)
{
ExplodedNode *Pred = *i;
const LocationContext *LC = Pred->getLocationContext();
const ProgramState *state = Pred->getState();
state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
Bldr.generateNode(E, Pred, state);
}
}
// Do the post visit.
getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
}
示例11: VisitCXXConstructExpr
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNode *Pred,
ExplodedNodeSet &destNodes) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
SVal Target = UnknownVal();
if (Optional<SVal> ElidedTarget =
getObjectUnderConstruction(State, CE, LCtx)) {
// We've previously modeled an elidable constructor by pretending that it in
// fact constructs into the correct target. This constructor can therefore
// be skipped.
Target = *ElidedTarget;
StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
State = finishObjectConstruction(State, CE, LCtx);
if (auto L = Target.getAs<Loc>())
State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType()));
Bldr.generateNode(CE, Pred, State);
return;
}
// FIXME: Handle arrays, which run the same constructor for every element.
// For now, we just run the first constructor (which should still invalidate
// the entire array).
EvalCallOptions CallOpts;
auto C = getCurrentCFGElement().getAs<CFGConstructor>();
assert(C || getCurrentCFGElement().getAs<CFGStmt>());
const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
std::tie(State, Target) =
prepareForObjectConstruction(CE, State, LCtx, CC, CallOpts);
break;
}
case CXXConstructExpr::CK_VirtualBase:
// Make sure we are not calling virtual base class initializers twice.
// Only the most-derived object should initialize virtual base classes.
if (const Stmt *Outer = LCtx->getStackFrame()->getCallSite()) {
const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer);
if (OuterCtor) {
switch (OuterCtor->getConstructionKind()) {
case CXXConstructExpr::CK_NonVirtualBase:
case CXXConstructExpr::CK_VirtualBase:
// Bail out!
destNodes.Add(Pred);
return;
case CXXConstructExpr::CK_Complete:
case CXXConstructExpr::CK_Delegating:
break;
}
}
}
LLVM_FALLTHROUGH;
case CXXConstructExpr::CK_NonVirtualBase:
// In C++17, classes with non-virtual bases may be aggregates, so they would
// be initialized as aggregates without a constructor call, so we may have
// a base class constructed directly into an initializer list without
// having the derived-class constructor call on the previous stack frame.
// Initializer lists may be nested into more initializer lists that
// correspond to surrounding aggregate initializations.
// FIXME: For now this code essentially bails out. We need to find the
// correct target region and set it.
// FIXME: Instead of relying on the ParentMap, we should have the
// trigger-statement (InitListExpr in this case) passed down from CFG or
// otherwise always available during construction.
if (dyn_cast_or_null<InitListExpr>(LCtx->getParentMap().getParent(CE))) {
MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(CE, LCtx));
CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
break;
}
LLVM_FALLTHROUGH;
case CXXConstructExpr::CK_Delegating: {
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
LCtx->getStackFrame());
SVal ThisVal = State->getSVal(ThisPtr);
if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) {
Target = ThisVal;
} else {
// Cast to the base type.
bool IsVirtual =
(CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase);
SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(),
IsVirtual);
Target = BaseVal;
}
break;
}
}
if (State != Pred->getState()) {
static SimpleProgramPointTag T("ExprEngine",
"Prepare for object construction");
ExplodedNodeSet DstPrepare;
StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx);
//.........这里部分代码省略.........
示例12: processCallExit
/// The call exit is simulated with a sequence of nodes, which occur between
/// CallExitBegin and CallExitEnd. The following operations occur between the
/// two program points:
/// 1. CallExitBegin (triggers the start of call exit sequence)
/// 2. Bind the return value
/// 3. Run Remove dead bindings to clean up the dead symbols from the callee.
/// 4. CallExitEnd (switch to the caller context)
/// 5. PostStmt<CallExpr>
void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// Step 1 CEBNode was generated before the call.
const StackFrameContext *calleeCtx =
CEBNode->getLocationContext()->getCurrentStackFrame();
// The parent context might not be a stack frame, so make sure we
// look up the first enclosing stack frame.
const StackFrameContext *callerCtx =
calleeCtx->getParent()->getCurrentStackFrame();
const Stmt *CE = calleeCtx->getCallSite();
ProgramStateRef state = CEBNode->getState();
// Find the last statement in the function and the corresponding basic block.
const Stmt *LastSt = 0;
const CFGBlock *Blk = 0;
llvm::tie(LastSt, Blk) = getLastStmt(CEBNode);
// Step 2: generate node with binded return value: CEBNode -> BindedRetNode.
// If the callee returns an expression, bind its value to CallExpr.
if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
const LocationContext *LCtx = CEBNode->getLocationContext();
SVal V = state->getSVal(RS, LCtx);
state = state->BindExpr(CE, callerCtx, V);
}
// Bind the constructed object value to CXXConstructExpr.
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
loc::MemRegionVal This =
svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
SVal ThisV = state->getSVal(This);
// Always bind the region to the CXXConstructExpr.
state = state->BindExpr(CCE, CEBNode->getLocationContext(), ThisV);
}
static SimpleProgramPointTag retValBindTag("ExprEngine : Bind Return Value");
PostStmt Loc(LastSt, calleeCtx, &retValBindTag);
bool isNew;
ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
BindedRetNode->addPredecessor(CEBNode, G);
if (!isNew)
return;
// Step 3: BindedRetNode -> CleanedNodes
// If we can find a statement and a block in the inlined function, run remove
// dead bindings before returning from the call. This is important to ensure
// that we report the issues such as leaks in the stack contexts in which
// they occurred.
ExplodedNodeSet CleanedNodes;
if (LastSt && Blk) {
NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
currentBuilderContext = &Ctx;
// Here, we call the Symbol Reaper with 0 statement and caller location
// context, telling it to clean up everything in the callee's context
// (and it's children). We use LastStmt as a diagnostic statement, which
// which the PreStmtPurge Dead point will be associated.
removeDead(BindedRetNode, CleanedNodes, 0, callerCtx, LastSt,
ProgramPoint::PostStmtPurgeDeadSymbolsKind);
currentBuilderContext = 0;
} else {
CleanedNodes.Add(CEBNode);
}
for (ExplodedNodeSet::iterator I = CleanedNodes.begin(),
E = CleanedNodes.end(); I != E; ++I) {
// Step 4: Generate the CallExit and leave the callee's context.
// CleanedNodes -> CEENode
CallExitEnd Loc(CE, callerCtx);
bool isNew;
ExplodedNode *CEENode = G.getNode(Loc, (*I)->getState(), false, &isNew);
CEENode->addPredecessor(*I, G);
if (!isNew)
return;
// Step 5: Perform the post-condition check of the CallExpr and enqueue the
// result onto the work list.
// CEENode -> Dst -> WorkList
ExplodedNodeSet Dst;
NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), CEENode);
SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext,
&Ctx);
SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
getCheckerManager().runCheckersForPostStmt(Dst, CEENode, CE, *this, true);
// Enqueue the next element in the block.
for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end();
PSI != PSE; ++PSI) {
Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(),
//.........这里部分代码省略.........