forked from OSchip/llvm-project
[analyzer] Reduce code duplication: make CXXDestructorCall a CXXInstanceCall.
While there is now some duplication between SimpleCall and the CXXInstanceCall sub-hierarchy, this is much better than copy-and-pasting the devirtualization logic shared by both instance methods and destructors. An unfortunate side effect is that there is no longer a single CallEvent type that corresponds to "calls written as CallExprs". For the most part this is a good thing, but the checker callback eval::Call still takes a CallExpr rather than a CallEvent (since we're not sure if we want to allow checkers to evaluate other kinds of calls). A mistake here will be caught by a cast<> in CheckerManager::runCheckersForEvalCall. No functionality change. llvm-svn: 161809
This commit is contained in:
parent
710f6b1259
commit
ce6c99a559
|
@ -319,9 +319,11 @@ public:
|
|||
SVal Cond, bool Assumption);
|
||||
|
||||
/// \brief Run checkers for evaluating a call.
|
||||
///
|
||||
/// Warning: Currently, the CallEvent MUST come from a CallExpr!
|
||||
void runCheckersForEvalCall(ExplodedNodeSet &Dst,
|
||||
const ExplodedNodeSet &Src,
|
||||
const SimpleCall &CE, ExprEngine &Eng);
|
||||
const CallEvent &CE, ExprEngine &Eng);
|
||||
|
||||
/// \brief Run checkers for the entire Translation Unit.
|
||||
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
|
||||
|
|
|
@ -32,15 +32,15 @@ namespace ento {
|
|||
|
||||
enum CallEventKind {
|
||||
CE_Function,
|
||||
CE_CXXMember,
|
||||
CE_CXXMemberOperator,
|
||||
CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember,
|
||||
CE_END_CXX_INSTANCE_CALLS = CE_CXXMemberOperator,
|
||||
CE_Block,
|
||||
CE_BEG_SIMPLE_CALLS = CE_Function,
|
||||
CE_END_SIMPLE_CALLS = CE_Block,
|
||||
CE_CXXConstructor,
|
||||
CE_CXXMember,
|
||||
CE_CXXMemberOperator,
|
||||
CE_CXXDestructor,
|
||||
CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember,
|
||||
CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor,
|
||||
CE_CXXConstructor,
|
||||
CE_CXXAllocator,
|
||||
CE_BEG_FUNCTION_CALLS = CE_Function,
|
||||
CE_END_FUNCTION_CALLS = CE_CXXAllocator,
|
||||
|
@ -377,7 +377,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a call to a written as a CallExpr.
|
||||
/// \brief Represents a call to a non-C++ function, written as a CallExpr.
|
||||
class SimpleCall : public AnyFunctionCall {
|
||||
protected:
|
||||
SimpleCall(const CallExpr *CE, ProgramStateRef St,
|
||||
|
@ -426,109 +426,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a non-static C++ member function call, no matter how
|
||||
/// it is written.
|
||||
class CXXInstanceCall : public SimpleCall {
|
||||
protected:
|
||||
virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
|
||||
|
||||
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: SimpleCall(CE, St, LCtx) {}
|
||||
|
||||
CXXInstanceCall(const CXXInstanceCall &Other) : SimpleCall(Other) {}
|
||||
|
||||
public:
|
||||
/// \brief Returns the expression representing the implicit 'this' object.
|
||||
virtual const Expr *getCXXThisExpr() const = 0;
|
||||
|
||||
/// \brief Returns the value of the implicit 'this' object.
|
||||
SVal getCXXThisVal() const {
|
||||
const Expr *Base = getCXXThisExpr();
|
||||
// FIXME: This doesn't handle an overloaded ->* operator.
|
||||
if (!Base)
|
||||
return UnknownVal();
|
||||
return getSVal(Base);
|
||||
}
|
||||
|
||||
virtual RuntimeDefinition getRuntimeDefinition() const;
|
||||
|
||||
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
|
||||
BindingsTy &Bindings) const;
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS &&
|
||||
CA->getKind() <= CE_END_CXX_INSTANCE_CALLS;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a non-static C++ member function call.
|
||||
///
|
||||
/// Example: \c obj.fun()
|
||||
class CXXMemberCall : public CXXInstanceCall {
|
||||
friend class CallEventManager;
|
||||
|
||||
protected:
|
||||
CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: CXXInstanceCall(CE, St, LCtx) {}
|
||||
|
||||
CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {}
|
||||
virtual void cloneTo(void *Dest) const { new (Dest) CXXMemberCall(*this); }
|
||||
|
||||
public:
|
||||
virtual const CXXMemberCallExpr *getOriginExpr() const {
|
||||
return cast<CXXMemberCallExpr>(SimpleCall::getOriginExpr());
|
||||
}
|
||||
|
||||
virtual const Expr *getCXXThisExpr() const;
|
||||
|
||||
virtual Kind getKind() const { return CE_CXXMember; }
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() == CE_CXXMember;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ overloaded operator call where the operator is
|
||||
/// implemented as a non-static member function.
|
||||
///
|
||||
/// Example: <tt>iter + 1</tt>
|
||||
class CXXMemberOperatorCall : public CXXInstanceCall {
|
||||
friend class CallEventManager;
|
||||
|
||||
protected:
|
||||
CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: CXXInstanceCall(CE, St, LCtx) {}
|
||||
|
||||
CXXMemberOperatorCall(const CXXMemberOperatorCall &Other)
|
||||
: CXXInstanceCall(Other) {}
|
||||
virtual void cloneTo(void *Dest) const {
|
||||
new (Dest) CXXMemberOperatorCall(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const CXXOperatorCallExpr *getOriginExpr() const {
|
||||
return cast<CXXOperatorCallExpr>(SimpleCall::getOriginExpr());
|
||||
}
|
||||
|
||||
virtual unsigned getNumArgs() const {
|
||||
return getOriginExpr()->getNumArgs() - 1;
|
||||
}
|
||||
virtual const Expr *getArgExpr(unsigned Index) const {
|
||||
return getOriginExpr()->getArg(Index + 1);
|
||||
}
|
||||
|
||||
virtual const Expr *getCXXThisExpr() const;
|
||||
|
||||
virtual Kind getKind() const { return CE_CXXMemberOperator; }
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() == CE_CXXMemberOperator;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a call to a block.
|
||||
///
|
||||
/// Example: <tt>^{ /* ... */ }()</tt>
|
||||
|
@ -581,6 +478,165 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a non-static C++ member function call, no matter how
|
||||
/// it is written.
|
||||
class CXXInstanceCall : public AnyFunctionCall {
|
||||
protected:
|
||||
virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
|
||||
|
||||
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: AnyFunctionCall(CE, St, LCtx) {}
|
||||
CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: AnyFunctionCall(D, St, LCtx) {}
|
||||
|
||||
|
||||
CXXInstanceCall(const CXXInstanceCall &Other) : AnyFunctionCall(Other) {}
|
||||
|
||||
public:
|
||||
/// \brief Returns the expression representing the implicit 'this' object.
|
||||
virtual const Expr *getCXXThisExpr() const { return 0; }
|
||||
|
||||
/// \brief Returns the value of the implicit 'this' object.
|
||||
virtual SVal getCXXThisVal() const {
|
||||
const Expr *Base = getCXXThisExpr();
|
||||
// FIXME: This doesn't handle an overloaded ->* operator.
|
||||
if (!Base)
|
||||
return UnknownVal();
|
||||
return getSVal(Base);
|
||||
}
|
||||
|
||||
virtual const FunctionDecl *getDecl() const;
|
||||
|
||||
virtual RuntimeDefinition getRuntimeDefinition() const;
|
||||
|
||||
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
|
||||
BindingsTy &Bindings) const;
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS &&
|
||||
CA->getKind() <= CE_END_CXX_INSTANCE_CALLS;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a non-static C++ member function call.
|
||||
///
|
||||
/// Example: \c obj.fun()
|
||||
class CXXMemberCall : public CXXInstanceCall {
|
||||
friend class CallEventManager;
|
||||
|
||||
protected:
|
||||
CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: CXXInstanceCall(CE, St, LCtx) {}
|
||||
|
||||
CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {}
|
||||
virtual void cloneTo(void *Dest) const { new (Dest) CXXMemberCall(*this); }
|
||||
|
||||
public:
|
||||
virtual const CXXMemberCallExpr *getOriginExpr() const {
|
||||
return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr());
|
||||
}
|
||||
|
||||
virtual unsigned getNumArgs() const {
|
||||
if (const CallExpr *CE = getOriginExpr())
|
||||
return CE->getNumArgs();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual const Expr *getArgExpr(unsigned Index) const {
|
||||
return getOriginExpr()->getArg(Index);
|
||||
}
|
||||
|
||||
virtual const Expr *getCXXThisExpr() const;
|
||||
|
||||
virtual Kind getKind() const { return CE_CXXMember; }
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() == CE_CXXMember;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ overloaded operator call where the operator is
|
||||
/// implemented as a non-static member function.
|
||||
///
|
||||
/// Example: <tt>iter + 1</tt>
|
||||
class CXXMemberOperatorCall : public CXXInstanceCall {
|
||||
friend class CallEventManager;
|
||||
|
||||
protected:
|
||||
CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: CXXInstanceCall(CE, St, LCtx) {}
|
||||
|
||||
CXXMemberOperatorCall(const CXXMemberOperatorCall &Other)
|
||||
: CXXInstanceCall(Other) {}
|
||||
virtual void cloneTo(void *Dest) const {
|
||||
new (Dest) CXXMemberOperatorCall(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const CXXOperatorCallExpr *getOriginExpr() const {
|
||||
return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr());
|
||||
}
|
||||
|
||||
virtual unsigned getNumArgs() const {
|
||||
return getOriginExpr()->getNumArgs() - 1;
|
||||
}
|
||||
virtual const Expr *getArgExpr(unsigned Index) const {
|
||||
return getOriginExpr()->getArg(Index + 1);
|
||||
}
|
||||
|
||||
virtual const Expr *getCXXThisExpr() const;
|
||||
|
||||
virtual Kind getKind() const { return CE_CXXMemberOperator; }
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() == CE_CXXMemberOperator;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents an implicit call to a C++ destructor.
|
||||
///
|
||||
/// This can occur at the end of a scope (for automatic objects), at the end
|
||||
/// of a full-expression (for temporaries), or as part of a delete.
|
||||
class CXXDestructorCall : public CXXInstanceCall {
|
||||
friend class CallEventManager;
|
||||
|
||||
protected:
|
||||
/// Creates an implicit destructor.
|
||||
///
|
||||
/// \param DD The destructor that will be called.
|
||||
/// \param Trigger The statement whose completion causes this destructor call.
|
||||
/// \param Target The object region to be destructed.
|
||||
/// \param St The path-sensitive state at this point in the program.
|
||||
/// \param LCtx The location context at this point in the program.
|
||||
CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
|
||||
const MemRegion *Target, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: CXXInstanceCall(DD, St, LCtx) {
|
||||
Data = Target;
|
||||
Location = Trigger->getLocEnd();
|
||||
}
|
||||
|
||||
CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {}
|
||||
virtual void cloneTo(void *Dest) const { new (Dest) CXXDestructorCall(*this); }
|
||||
|
||||
public:
|
||||
virtual SourceRange getSourceRange() const { return Location; }
|
||||
virtual unsigned getNumArgs() const { return 0; }
|
||||
|
||||
/// \brief Returns the value of the implicit 'this' object.
|
||||
virtual SVal getCXXThisVal() const;
|
||||
|
||||
virtual Kind getKind() const { return CE_CXXDestructor; }
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() == CE_CXXDestructor;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a call to a C++ constructor.
|
||||
///
|
||||
/// Example: \c T(1)
|
||||
|
@ -622,7 +678,7 @@ public:
|
|||
}
|
||||
|
||||
/// \brief Returns the value of the implicit 'this' object.
|
||||
virtual SVal getCXXThisVal() const;
|
||||
SVal getCXXThisVal() const;
|
||||
|
||||
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
|
||||
BindingsTy &Bindings) const;
|
||||
|
@ -634,53 +690,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Represents an implicit call to a C++ destructor.
|
||||
///
|
||||
/// This can occur at the end of a scope (for automatic objects), at the end
|
||||
/// of a full-expression (for temporaries), or as part of a delete.
|
||||
class CXXDestructorCall : public AnyFunctionCall {
|
||||
friend class CallEventManager;
|
||||
|
||||
protected:
|
||||
/// Creates an implicit destructor.
|
||||
///
|
||||
/// \param DD The destructor that will be called.
|
||||
/// \param Trigger The statement whose completion causes this destructor call.
|
||||
/// \param Target The object region to be destructed.
|
||||
/// \param St The path-sensitive state at this point in the program.
|
||||
/// \param LCtx The location context at this point in the program.
|
||||
CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
|
||||
const MemRegion *Target, ProgramStateRef St,
|
||||
const LocationContext *LCtx)
|
||||
: AnyFunctionCall(DD, St, LCtx) {
|
||||
Data = Target;
|
||||
Location = Trigger->getLocEnd();
|
||||
}
|
||||
|
||||
CXXDestructorCall(const CXXDestructorCall &Other) : AnyFunctionCall(Other) {}
|
||||
virtual void cloneTo(void *Dest) const { new (Dest) CXXDestructorCall(*this); }
|
||||
|
||||
virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
|
||||
|
||||
public:
|
||||
virtual SourceRange getSourceRange() const { return Location; }
|
||||
virtual unsigned getNumArgs() const { return 0; }
|
||||
|
||||
/// \brief Returns the value of the implicit 'this' object.
|
||||
virtual SVal getCXXThisVal() const;
|
||||
|
||||
virtual RuntimeDefinition getRuntimeDefinition() const;
|
||||
|
||||
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
|
||||
BindingsTy &Bindings) const;
|
||||
|
||||
virtual Kind getKind() const { return CE_CXXDestructor; }
|
||||
|
||||
static bool classof(const CallEvent *CA) {
|
||||
return CA->getKind() == CE_CXXDestructor;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents the memory allocation call in a C++ new-expression.
|
||||
///
|
||||
/// This is a call to "operator new".
|
||||
|
@ -874,7 +883,7 @@ public:
|
|||
getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State);
|
||||
|
||||
|
||||
CallEventRef<SimpleCall>
|
||||
CallEventRef<>
|
||||
getSimpleCall(const CallExpr *E, ProgramStateRef State,
|
||||
const LocationContext *LCtx);
|
||||
|
||||
|
|
|
@ -463,8 +463,10 @@ public:
|
|||
const LocationContext *LCtx,
|
||||
ProgramStateRef State);
|
||||
|
||||
/// Evaluate a call, running pre- and post-call checks and allowing checkers
|
||||
/// to be responsible for handling the evaluation of the call itself.
|
||||
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
|
||||
const SimpleCall &Call);
|
||||
const CallEvent &Call);
|
||||
|
||||
/// \brief Default implementation of call evaluation.
|
||||
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
|
||||
|
|
|
@ -355,6 +355,18 @@ const FunctionDecl *SimpleCall::getDecl() const {
|
|||
}
|
||||
|
||||
|
||||
const FunctionDecl *CXXInstanceCall::getDecl() const {
|
||||
const CallExpr *CE = cast_or_null<CallExpr>(getOriginExpr());
|
||||
if (!CE)
|
||||
return AnyFunctionCall::getDecl();
|
||||
|
||||
const FunctionDecl *D = CE->getDirectCallee();
|
||||
if (D)
|
||||
return D;
|
||||
|
||||
return getSVal(CE->getCallee()).getAsFunctionDecl();
|
||||
}
|
||||
|
||||
void CXXInstanceCall::getExtraInvalidatedRegions(RegionList &Regions) const {
|
||||
if (const MemRegion *R = getCXXThisVal().getAsRegion())
|
||||
Regions.push_back(R);
|
||||
|
@ -389,7 +401,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
|
|||
|
||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
|
||||
if (!MD->isVirtual())
|
||||
return SimpleCall::getRuntimeDefinition();
|
||||
return AnyFunctionCall::getRuntimeDefinition();
|
||||
|
||||
// If the method is virtual, see if we can find the actual implementation
|
||||
// based on context-sensitivity.
|
||||
|
@ -527,46 +539,6 @@ SVal CXXDestructorCall::getCXXThisVal() const {
|
|||
return UnknownVal();
|
||||
}
|
||||
|
||||
void CXXDestructorCall::getExtraInvalidatedRegions(RegionList &Regions) const {
|
||||
if (Data)
|
||||
Regions.push_back(static_cast<const MemRegion *>(Data));
|
||||
}
|
||||
|
||||
RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const {
|
||||
const Decl *D = AnyFunctionCall::getRuntimeDefinition().getDecl();
|
||||
if (!D)
|
||||
return RuntimeDefinition();
|
||||
|
||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
|
||||
if (!MD->isVirtual())
|
||||
return RuntimeDefinition(MD);
|
||||
|
||||
// If the method is virtual, see if we can find the actual implementation
|
||||
// based on context-sensitivity.
|
||||
// FIXME: Virtual method calls behave differently when an object is being
|
||||
// constructed or destructed. It's not as simple as "no devirtualization"
|
||||
// because a /partially/ constructed object can be referred to through a
|
||||
// base pointer. We'll eventually want to use DynamicTypeInfo here.
|
||||
if (const CXXMethodDecl *Devirtualized = devirtualize(MD, getCXXThisVal()))
|
||||
return RuntimeDefinition(Devirtualized);
|
||||
|
||||
return RuntimeDefinition();
|
||||
}
|
||||
|
||||
void CXXDestructorCall::getInitialStackFrameContents(
|
||||
const StackFrameContext *CalleeCtx,
|
||||
BindingsTy &Bindings) const {
|
||||
AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings);
|
||||
|
||||
SVal ThisVal = getCXXThisVal();
|
||||
if (!ThisVal.isUnknown()) {
|
||||
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
|
||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
|
||||
Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
|
||||
Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CallEvent::param_iterator ObjCMethodCall::param_begin() const {
|
||||
const ObjCMethodDecl *D = getDecl();
|
||||
|
@ -805,7 +777,7 @@ void ObjCMethodCall::getInitialStackFrameContents(
|
|||
}
|
||||
}
|
||||
|
||||
CallEventRef<SimpleCall>
|
||||
CallEventRef<>
|
||||
CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
|
||||
const LocationContext *LCtx) {
|
||||
if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE))
|
||||
|
|
|
@ -504,9 +504,9 @@ CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
|
|||
/// Only one checker will evaluate the call.
|
||||
void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
|
||||
const ExplodedNodeSet &Src,
|
||||
const SimpleCall &Call,
|
||||
const CallEvent &Call,
|
||||
ExprEngine &Eng) {
|
||||
const CallExpr *CE = Call.getOriginExpr();
|
||||
const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
|
||||
for (ExplodedNodeSet::iterator
|
||||
NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
|
||||
|
||||
|
|
|
@ -445,7 +445,7 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
|
|||
// Get the call in its initial state. We use this as a template to perform
|
||||
// all the checks.
|
||||
CallEventManager &CEMgr = getStateManager().getCallEventManager();
|
||||
CallEventRef<SimpleCall> CallTemplate
|
||||
CallEventRef<> CallTemplate
|
||||
= CEMgr.getSimpleCall(CE, Pred->getState(), Pred->getLocationContext());
|
||||
|
||||
// Evaluate the function call. We try each of the checkers
|
||||
|
@ -465,7 +465,7 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
|
|||
}
|
||||
|
||||
void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
|
||||
const SimpleCall &Call) {
|
||||
const CallEvent &Call) {
|
||||
// WARNING: At this time, the state attached to 'Call' may be older than the
|
||||
// state in 'Pred'. This is a minor optimization since CheckerManager will
|
||||
// use an updated CallEvent instance when calling checkers, but if 'Call' is
|
||||
|
|
Loading…
Reference in New Issue