22 #include "llvm/ADT/SmallSet.h"
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/Support/SaveAndRestore.h"
26 using namespace clang;
29 #define DEBUG_TYPE "ExprEngine"
32 "The # of times we split the path due to imprecise dynamic dispatch info");
35 "The # of times we inlined a call");
38 "The # of times we reached inline count maximum");
45 const CFG *CalleeCFG = calleeCtx->
getCFG();
49 assert(Entry->
empty());
70 static std::pair<
const Stmt*,
72 const Stmt *
S =
nullptr;
87 S = CEE->getCalleeContext()->getCallSite();
98 }
while (!CE || CE->getCalleeContext() != CEE->getCalleeContext());
106 if (CE->getCalleeContext() == SF)
111 return std::make_pair(
nullptr,
nullptr);
116 return std::make_pair(S, Blk);
133 if (ExpectedTy == ActualTy)
144 if (ExpectedClass && ActualClass) {
163 const Stmt *LastSt =
nullptr;
166 if (!Blk || !LastSt) {
178 removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), LCtx,
186 const Decl *StaticDecl = Call->getDecl();
187 assert(RuntimeCallee);
207 return isa<CXXTempObjectRegion>(MR);
229 const Stmt *CE = calleeCtx->getCallSite();
232 const Stmt *LastSt =
nullptr;
245 if (
const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
247 SVal V = state->getSVal(RS, LCtx);
253 if (!ReturnedTy.
isNull()) {
254 if (
const Expr *Ex = dyn_cast<Expr>(CE)) {
261 state = state->BindExpr(CE, callerCtx, V);
267 svalBuilder.
getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
268 SVal ThisV = state->getSVal(This);
272 ThisV = state->getSVal(ThisV.
castAs<
Loc>());
274 state = state->BindExpr(CCE, callerCtx, ThisV);
299 removeDead(BindedRetNode, CleanedNodes,
nullptr, calleeCtx,
300 calleeCtx->getAnalysisDeclContext()->getBody(),
302 currBldrCtx =
nullptr;
304 CleanedNodes.
Add(CEBNode);
308 E = CleanedNodes.
end(); I != E; ++I) {
351 calleeCtx->getIndex()+1);
357 bool &IsRecursive,
unsigned &StackDepth) {
363 const Decl *DI = SFC->getDecl();
376 const CFG *CalleeCFG = CalleeADC->
getCFG();
392 if (!isa<NamespaceDecl>(Parent))
394 ND = cast<NamespaceDecl>(Parent);
408 DynamicDispatchModeInlined = 1,
409 DynamicDispatchModeConservative
426 assert(BR &&
"If we have the block definition we should have its region");
434 const Expr *CallE = Call.getOriginExpr();
440 currBldrCtx->getBlock(),
448 State = State->enterStackFrame(Call, CalleeSFC);
451 if (
ExplodedNode *N = G.getNode(Loc, State,
false, &isNew)) {
452 N->addPredecessor(Pred, G);
454 Engine.getWorkList()->enqueue(N);
459 Bldr.takeNodes(Pred);
465 VisitedCallees->insert(D);
476 assert(ReplayState == CallE &&
"Backtracked to the wrong call.");
499 evalCall(dstCallEvaluated, *I, *CallTemplate);
543 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
544 switch (Msg->getMethodFamily()) {
551 return State->BindExpr(E, LCtx, Msg->getReceiverSVal());
555 SVal ThisV =
C->getCXXThisVal();
559 ThisV = State->getSVal(ThisV.
castAs<
Loc>());
561 return State->BindExpr(E, LCtx, ThisV);
569 return State->BindExpr(E, LCtx, R);
614 if (Target && isa<ElementRegion>(Target))
623 if (isa<CXXNewExpr>(Parent))
643 if (!Target || !isa<DeclRegion>(Target))
660 const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion();
661 if (Target && isa<ElementRegion>(Target))
732 if (II->isStr(
"shared_ptr"))
784 const CFG *CalleeCFG = CalleeADC->
getCFG();
800 bool ExprEngine::shouldInlineCall(
const CallEvent &Call,
const Decl *D,
813 if (isa<CXXDestructorCall>(Call)) {
814 if ((*currBldrCtx->
getBlock())[currStmtIdx].getAs<CFGTemporaryDtor>())
829 if (MayInline.hasValue()) {
830 if (!MayInline.getValue())
851 assert(!MayInline.hasValue() || MayInline.getValue());
857 const CFG *CalleeCFG = CalleeADC->
getCFG();
860 bool IsRecursive =
false;
861 unsigned StackDepth = 0;
872 NumReachedInlineCountMax++;
908 performTrivialCopy(Bldr, Pred, *Call);
915 const Expr *E = Call->getOriginExpr();
918 if (InlinedFailedState) {
920 State = InlinedFailedState;
924 if (shouldInlineCall(*Call, D, Pred)) {
936 conservativeEvalCall(*Call, Bldr, Pred, State);
942 if (inlineCall(*Call, D, Bldr, Pred, State))
948 conservativeEvalCall(*Call, Bldr, Pred, State);
951 void ExprEngine::BifurcateCall(
const MemRegion *BifurReg,
960 const unsigned *BState =
961 State->get<DynamicDispatchBifurcationMap>(BifurReg);
964 if (*BState == DynamicDispatchModeInlined)
965 if (inlineCall(Call, D, Bldr, Pred, State))
970 conservativeEvalCall(Call, Bldr, Pred, State);
977 State->set<DynamicDispatchBifurcationMap>(BifurReg,
978 DynamicDispatchModeInlined);
979 inlineCall(Call, D, Bldr, Pred, IState);
982 State->set<DynamicDispatchBifurcationMap>(BifurReg,
983 DynamicDispatchModeConservative);
984 conservativeEvalCall(Call, Bldr, Pred, NoIState);
986 NumOfDynamicDispatchPathSplits++;
1001 ei = dstPreVisit.
end(); it != ei; ++it) {
AnalysisDeclContextManager & getAnalysisDeclContextManager()
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
unsigned InlineMaxStackDepth
The inlining stack depth limit.
ASTContext & getASTContext() const
SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)
MemRegion - The root abstract class for all memory regions.
const CXXConstructorDecl * getDecl() const override
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
succ_iterator succ_begin()
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
void processCallExit(ExplodedNode *Pred) override
const StackFrameContext * getCalleeContext() const
This builder class is useful for generating nodes that resulted from visiting a statement. The main difference from its parent NodeBuilder is that it creates a statement specific ProgramPoint.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
static bool mayInlineDecl(AnalysisDeclContext *CalleeADC, AnalyzerOptions &Opts)
Manages the lifetime of CallEvent objects.
Optional< bool > mayInline(const Decl *D)
static bool isContainerMethod(const ASTContext &Ctx, const FunctionDecl *FD)
IdentifierInfo * getAsIdentifierInfo() const
bool isStdNamespace() const
void markShouldNotInline(const Decl *D)
NamespaceDecl - Represent a C++ namespace.
Represents a call to a C++ constructor.
virtual const CXXConstructExpr * getOriginExpr() const
static bool IsInStdNamespace(const FunctionDecl *FD)
CallEventRef getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx)
static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call, const StackFrameContext *calleeCtx)
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
CallEventRef< T > cloneWithState(ProgramStateRef NewState) const
Returns a copy of this CallEvent, but using the given state.
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
unsigned succ_size() const
static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD, StringRef Name)
Returns true if the given C++ class contains a member with the given name.
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)
Run the analyzer's garbage collection - remove dead symbols and bindings from the state...
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool mayInlineTemplateFunctions()
ImplTy::iterator iterator
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call. May be null.
const CXXRecordDecl * getPointeeCXXRecordDecl() const
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting obj-c messages.
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
Represents any expression that calls an Objective-C method.
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
bool shouldInlineCall() const
virtual Kind getKind() const =0
Returns the kind of call this is.
const LangOptions & getLangOpts() const
unsigned getNumTimesInlined(const Decl *D)
void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng)
Run checkers for pre-visiting obj-c messages.
bool mayInlineCXXContainerMethods()
const CXXRecordDecl * getParent() const
void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitReturnStmt - Transfer function logic for return statements.
ProgramPoint getProgramPoint(bool IsPreVisit=false, const ProgramPointTag *Tag=nullptr) const
Returns an appropriate ProgramPoint for this call.
const Decl * getDecl() const
ExplodedNode * getFirstPred()
void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting obj-c messages.
static bool isCXXSharedPtrDtor(const FunctionDecl *FD)
static bool isVariadic(const Decl *D)
Returns true if the given decl is known to be variadic.
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
unsigned getMaxInlinableSize()
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
const LocationContext * getLocationContext() const
void removeDeadOnEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
static bool isTrivialObjectAssignment(const CallEvent &Call)
ProgramStateRef bindReturnValue(const CallEvent &Call, const LocationContext *LCtx, ProgramStateRef State)
Create a new state in which the call return value is binded to the call origin expression.
CanQualType getCanonicalTypeUnqualified() const
Represents a non-static C++ member function call, no matter how it is written.
static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy, StoreManager &StoreMgr)
DeclarationNameTable DeclarationNames
Stmt * getBody() const
Get the body of the Declaration.
unsigned blockCount() const
Returns the number of times the current basic block has been visited on the exploded graph path...
const MemRegion * StripCasts(bool StripBaseCasts=true) const
CheckerManager & getCheckerManager() const
AnalysisDeclContext * getContext(const Decl *D)
void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting Stmts.
const ProgramStateRef & getState() const
IPAKind getIPAMode()
Returns the inter-procedural analysis mode.
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Represents an implicit call to a C++ destructor.
Represents a C++ destructor within a class.
ParentMap & getParentMap() const
This is the simplest builder which generates nodes in the ExplodedGraph.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
void Add(ExplodedNode *N)
Refers to regular member function and operator calls.
ConstructionKind getConstructionKind() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
bool mayInlineObjCMethod()
Returns true if ObjectiveC inlining is enabled, false otherwise.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng)
Run checkers for evaluating a call.
REGISTER_TRAIT_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap, CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, unsigned)) bool ExprEngine
DeclContext * getParent()
getParent - Returns the containing DeclContext.
void bumpNumTimesInlined(const Decl *D)
static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V)
DeclarationName getDeclName() const
ExplodedNode * getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false, bool *IsNew=nullptr)
Retrieve the node associated with a (Location,State) pair, where the 'Location' is a ProgramPoint in ...
const StackFrameContext * getStackFrame(LocationContext const *Parent, const Stmt *S, const CFGBlock *Blk, unsigned Idx)
Enable inlining of dynamically dispatched methods.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
const MatchFinder::MatchFinderOptions & Options
Defines the runtime definition of the called function.
unsigned getAlwaysInlineSize()
Stmt * getParent(Stmt *) const
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
const FunctionDecl * getDecl() const override
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
const StackFrameContext * getCurrentStackFrame() const
AnalysisManager & getAnalysisManager() override
CallEventManager & getCallEventManager()
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call)
bool mayInlineCXXStandardLibrary()
Represents a static or instance method of a struct/union/class.
#define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)
AnalyzerOptions & options
const Decl * getDecl() const
Do minimal inlining of callees.
Refers to destructors (implicit or explicit).
lookup_result lookup(DeclarationName Name) const
void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)
Run checkers for pre-visiting Stmts.
static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD)
const MemRegion * getDispatchRegion()
void insert(const ExplodedNodeSet &S)
ast_type_traits::DynTypedNode Node
ProgramStateRef invalidateRegions(unsigned BlockCount, ProgramStateRef Orig=nullptr) const
Returns a new state with all argument regions invalidated.
static ProgramStateRef getInlineFailedState(ProgramStateRef State, const Stmt *CallE)
const LocationContext * getParent() const
CFG::BuildOptions & getCFGBuildOptions()
Return the build options used to construct the CFG.
SValBuilder & getSValBuilder()
StoreManager & getStoreManager()
const LocationContext * getLocationContext() const
bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, CXXBasePaths &Paths) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
void markMayInline(const Decl *D)
bool isAmbiguous(CanQualType BaseType)
Determine whether the path from the most-derived type to the given base type is ambiguous (i...
const MemRegion * getAsRegion() const
const Expr * getRetValue() const
bool mayHaveOtherDefinitions()
Check if the definition we have is precise. If not, it is possible that the call dispatches to anothe...
Represents an abstract call to a function or method along a particular path.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
ProgramStateManager & getStateManager() override
const CFGBlock * getBlock() const
Return the CFGBlock associated with this builder.
QualType getResultType() const
Returns the result type, adjusted for references.
void * getAsOpaquePtr() const
QualType getCanonicalType() const
WorkList * getWorkList() const
static QualType getDeclaredResultType(const Decl *D)
Returns the result type of a function or method declaration.
void processCallEnter(CallEnter CE, ExplodedNode *Pred) override
Generate the entry node of the callee.
STATISTIC(NumOfDynamicDispatchPathSplits,"The # of times we split the path due to imprecise dynamic dispatch info")
SourceManager & getSourceManager()
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call)
Default implementation of call evaluation.
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a node in the ExplodedGraph.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Represents a C++ struct/union/class.
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K)
bool isObjCObjectPointerType() const
CallEventRef< T > cloneWithState(ProgramStateRef State) const
pred_iterator pred_begin()
SVal getCXXThisVal() const
Returns the value of the implicit 'this' object.
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
unsigned getMaxTimesInlineLarge()
static CallInlinePolicy mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, AnalyzerOptions &Opts)
virtual void enqueue(const WorkListUnit &U)=0
const BlockInvocationContext * getBlockInvocationContext(const LocationContext *parent, const BlockDecl *BD, const void *ContextData)
bool mayInlineCXXAllocator()
AnalysisPurgeMode AnalysisPurgeOpt
bool mayInlineCXXSharedPtrDtor()
bool isNull() const
isNull - Return true if this QualType doesn't point to a type yet.
unsigned getNumBlockIDs() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Represents a call to a C++ constructor.
const CoreEngine & getCoreEngine() const
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *Name)
Base-class lookup callback that determines whether there exists a member with the given name...