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");
48 assert(Entry->
empty());
73 static std::pair<
const Stmt*,
75 const Stmt *S =
nullptr;
90 S = CEE->getCalleeContext()->getCallSite();
101 }
while (!CE || CE->getCalleeContext() != CEE->getCalleeContext());
109 if (CE->getCalleeContext() == SF)
114 return std::make_pair(
nullptr,
nullptr);
119 return std::make_pair(S, Blk);
136 if (ExpectedTy == ActualTy)
147 if (ExpectedClass && ActualClass) {
166 const Stmt *LastSt =
nullptr;
169 if (!Blk || !LastSt) {
181 removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), LCtx,
189 const Decl *StaticDecl = Call->getDecl();
190 assert(RuntimeCallee);
210 return isa<CXXTempObjectRegion>(MR);
232 const Stmt *CE = calleeCtx->getCallSite();
235 const Stmt *LastSt =
nullptr;
248 if (
const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
250 SVal V = state->getSVal(RS, LCtx);
256 if (!ReturnedTy.
isNull()) {
257 if (
const Expr *Ex = dyn_cast<Expr>(CE)) {
264 state = state->BindExpr(CE, callerCtx, V);
270 svalBuilder.
getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
271 SVal ThisV = state->getSVal(This);
275 ThisV = state->getSVal(ThisV.
castAs<
Loc>());
277 state = state->BindExpr(CCE, callerCtx, ThisV);
302 removeDead(BindedRetNode, CleanedNodes,
nullptr, calleeCtx,
303 calleeCtx->getAnalysisDeclContext()->getBody(),
305 currBldrCtx =
nullptr;
307 CleanedNodes.
Add(CEBNode);
311 E = CleanedNodes.
end(); I != E; ++I) {
354 calleeCtx->getIndex()+1);
360 bool &IsRecursive,
unsigned &StackDepth) {
366 const Decl *DI = SFC->getDecl();
379 const CFG *CalleeCFG = CalleeADC->
getCFG();
395 DynamicDispatchModeInlined = 1,
396 DynamicDispatchModeConservative
404 bool ExprEngine::inlineCall(
const CallEvent &Call,
const Decl *D,
413 !cast<BlockCall>(Call).isConversionFromLambda()) {
415 assert(BR &&
"If we have the block definition we should have its region");
429 currBldrCtx->getBlock(),
436 State = State->enterStackFrame(Call, CalleeSFC);
439 if (
ExplodedNode *N = G.getNode(Loc, State,
false, &isNew)) {
440 N->addPredecessor(Pred, G);
442 Engine.getWorkList()->enqueue(N);
450 Engine.FunctionSummaries->bumpNumTimesInlined(D);
454 VisitedCallees->insert(D);
465 assert(ReplayState == CallE &&
"Backtracked to the wrong call.");
488 evalCall(dstCallEvaluated, *I, *CallTemplate);
532 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
533 switch (Msg->getMethodFamily()) {
540 return State->BindExpr(E, LCtx, Msg->getReceiverSVal());
544 SVal ThisV = C->getCXXThisVal();
548 ThisV = State->getSVal(ThisV.
castAs<
Loc>());
550 return State->BindExpr(E, LCtx, ThisV);
556 unsigned Count = currBldrCtx->blockCount();
558 return State->BindExpr(E, LCtx, R);
603 if (Target && isa<ElementRegion>(Target))
612 if (isa<CXXNewExpr>(
Parent))
632 if (!Target || !isa<DeclRegion>(Target))
649 const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion();
650 if (Target && isa<ElementRegion>(Target))
684 return CXXRecordDecl::FindOrdinaryMember(Specifier, Path, DeclName);
723 if (II->isStr(
"shared_ptr"))
774 const CFG *CalleeCFG = CalleeADC->
getCFG();
790 bool ExprEngine::shouldInlineCall(
const CallEvent &Call,
const Decl *D,
803 if (isa<CXXDestructorCall>(Call)) {
804 if ((*currBldrCtx->getBlock())[currStmtIdx].getAs<CFGTemporaryDtor>())
818 Optional<bool> MayInline = Engine.FunctionSummaries->mayInline(D);
819 if (MayInline.hasValue()) {
820 if (!MayInline.getValue())
827 Engine.FunctionSummaries->markMayInline(D);
829 Engine.FunctionSummaries->markShouldNotInline(D);
841 assert(!MayInline.hasValue() || MayInline.getValue());
842 Engine.FunctionSummaries->markShouldNotInline(D);
847 const CFG *CalleeCFG = CalleeADC->
getCFG();
850 bool IsRecursive =
false;
851 unsigned StackDepth = 0;
859 if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
863 NumReachedInlineCountMax++;
897 performTrivialCopy(Bldr, Pred, *Call);
904 const Expr *E = Call->getOriginExpr();
907 if (InlinedFailedState) {
909 State = InlinedFailedState;
913 if (shouldInlineCall(*Call, D, Pred)) {
925 conservativeEvalCall(*Call, Bldr, Pred, State);
931 if (inlineCall(*Call, D, Bldr, Pred, State))
937 conservativeEvalCall(*Call, Bldr, Pred, State);
940 void ExprEngine::BifurcateCall(
const MemRegion *BifurReg,
949 const unsigned *BState =
950 State->get<DynamicDispatchBifurcationMap>(BifurReg);
953 if (*BState == DynamicDispatchModeInlined)
954 if (inlineCall(Call, D, Bldr, Pred, State))
959 conservativeEvalCall(Call, Bldr, Pred, State);
966 State->set<DynamicDispatchBifurcationMap>(BifurReg,
967 DynamicDispatchModeInlined);
968 inlineCall(Call, D, Bldr, Pred, IState);
971 State->set<DynamicDispatchBifurcationMap>(BifurReg,
972 DynamicDispatchModeConservative);
973 conservativeEvalCall(Call, Bldr, Pred, NoIState);
975 NumOfDynamicDispatchPathSplits++;
987 ei = dstPreVisit.
end(); it != ei; ++it) {
AnalysisDeclContextManager & getAnalysisDeclContextManager()
An instance of this class is created to represent a function declaration or definition.
unsigned InlineMaxStackDepth
The inlining stack depth limit.
SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)
Evaluates a chain of derived-to-base casts through the path specified in Cast.
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
CallEventRef< T > cloneWithState(ProgramStateRef NewState) const
Returns a copy of this CallEvent, but using the given state.
const CXXConstructorDecl * getDecl() const override
Stmt * getBody() const
Get the body of the Declaration.
succ_iterator succ_begin()
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
void processCallExit(ExplodedNode *Pred) override
Generate the sequence of nodes that simulate the call exit and the post visit for CallExpr...
Stmt - This represents one statement.
This builder class is useful for generating nodes that resulted from visiting a statement.
ProgramPoint getProgramPoint(bool IsPreVisit=false, const ProgramPointTag *Tag=nullptr) const
Returns an appropriate ProgramPoint for this call.
Decl - This represents one declaration (or definition), e.g.
Represents a point when we begin processing an inlined call.
static bool mayInlineDecl(AnalysisDeclContext *CalleeADC, AnalyzerOptions &Opts)
Returns true if the function in CalleeADC may be inlined in general.
Manages the lifetime of CallEvent objects.
static bool isContainerMethod(const ASTContext &Ctx, const FunctionDecl *FD)
Returns true if the given function refers to a method of a C++ container or iterator.
Stmt * getParent(Stmt *) const
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
Represents a call to a C++ constructor.
const NestedNameSpecifier * Specifier
CallEventRef getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx)
const ProgramStateRef & getState() const
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call, const StackFrameContext *calleeCtx)
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
unsigned succ_size() const
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
void takeNodes(const ExplodedNodeSet &S)
ASTContext & getASTContext() const
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
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 enqueue(ExplodedNodeSet &Set)
Enqueue the given set of nodes onto the work list.
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 mayInlineTemplateFunctions()
Returns whether or not templated functions may be considered for inlining.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
const CFGBlock * getEntry() const
Returns the entry block in the CFG for the entered function.
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
One of these records is kept for each identifier that is lexed.
ImplTy::iterator iterator
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function or method under analysis.
const Expr * getRetValue() const
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...
void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting obj-c messages.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
STATISTIC(NumOfDynamicDispatchPathSplits, "The # of times we split the path due to imprecise dynamic dispatch info")
BlockDataRegion - A region that represents a block instance.
Represents any expression that calls an Objective-C method.
virtual Kind getKind() const =0
Returns the kind of call this is.
static bool isInStdNamespace(const Decl *D)
Returns true if the root namespace of the given declaration is the 'std' C++ namespace.
WorkList * getWorkList() const
void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng)
Run checkers for pre-visiting obj-c messages.
bool mayInlineCXXContainerMethods()
Returns whether or not methods of C++ container objects may be considered for inlining.
const StackFrameContext * getCurrentStackFrame() const
T * getAnalysis()
Return the specified analysis object, lazily running the analysis if necessary.
const LocationContext * getLocationContext() const
const LocationContext * getParent() const
virtual const CXXConstructExpr * getOriginExpr() const
unsigned getMinCFGSizeTreatFunctionsAsLarge()
Returns the number of basic blocks a function needs to have to be considered large for the 'max-times...
void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitReturnStmt - Transfer function logic for return statements.
const CoreEngine & getCoreEngine() const
ExplodedNode * getFirstPred()
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
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)
Returns true if the given function is the destructor of a class named "shared_ptr".
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()
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
CheckerManager & getCheckerManager() 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.
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)
Adjusts a return value when the called function's return type does not match the caller's expression ...
DeclarationNameTable DeclarationNames
CFGBlock - Represents a single basic block in a source-level CFG.
Represents a point when we finish the call exit sequence (for inlined call).
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.
void processBeginOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L) override
Called by CoreEngine.
Expr - This represents one expression.
IPAKind getIPAMode()
Returns the inter-procedural analysis mode.
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that that type refers to...
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Represents an implicit call to a C++ destructor.
Represents a C++ destructor within a class.
This is the simplest builder which generates nodes in the ExplodedGraph.
void Add(ExplodedNode *N)
Refers to regular member function and operator calls.
bool mayInlineObjCMethod()
Returns true if ObjectiveC inlining is enabled, false otherwise.
IdentifierInfo * getAsIdentifierInfo() const
getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in this declaration name, or NULL if this declaration name isn't a simple identifier.
Refers to constructors (implicit or explicit).
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng)
Run checkers for evaluating a call.
Traits for storing the call processing policy inside GDM.
REGISTER_TRAIT_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap, CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, unsigned)) bool ExprEngine
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V)
Returns true if the CXXConstructExpr E was intended to construct a prvalue for the region in V...
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)
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Enable inlining of dynamically dispatched methods.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
ParentMap & getParentMap() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
While alive, includes the current analysis stack in a crash trace.
CanQualType getCanonicalTypeUnqualified() const
const MemRegion * StripCasts(bool StripBaseCasts=true) const
Defines the runtime definition of the called function.
QualType getCanonicalType() const
unsigned getAlwaysInlineSize()
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.
AnalysisManager & getAnalysisManager() override
const MemRegion * getAsRegion() const
CallEventManager & getCallEventManager()
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call)
Evaluate a call, running pre- and post-call checks and allowing checkers to be responsible for handli...
bool mayInlineCXXStandardLibrary()
Returns whether or not C++ standard library functions may be considered for inlining.
Represents a static or instance method of a struct/union/class.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
#define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)
Helper for registering a map trait.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
const Decl * getDecl() const
bool isObjCObjectPointerType() const
AnalyzerOptions & options
Do minimal inlining of callees.
unsigned getNumBlockIDs() const
getNumBlockIDs - Returns the total number of BlockIDs allocated (which start at 0).
Refers to destructors (implicit or explicit).
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)
Returns true if the given C++ class is a container or iterator.
const MemRegion * getDispatchRegion()
When other definitions are possible, returns the region whose runtime type determines the method defi...
void insert(const ExplodedNodeSet &S)
ast_type_traits::DynTypedNode Node
static ProgramStateRef getInlineFailedState(ProgramStateRef State, const Stmt *CallE)
SVal getCXXThisVal() const
Returns the value of the implicit 'this' object.
Dataflow Directional Tag Classes.
CFG::BuildOptions & getCFGBuildOptions()
Return the build options used to construct the CFG.
SValBuilder & getSValBuilder()
StoreManager & getStoreManager()
const StackFrameContext * getCalleeContext() const
DeclarationName - The name of a declaration.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
bool isAmbiguous(CanQualType BaseType)
Determine whether the path from the most-derived type to the given base type is ambiguous (i...
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
bool mayHaveOtherDefinitions()
Check if the definition we have is precise.
Represents an abstract call to a function or method along a particular path.
ProgramStateManager & getStateManager() override
const Decl * getDecl() const
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
const LocationContext * getLocationContext() const
static QualType getDeclaredResultType(const Decl *D)
Returns the result type of a function or method declaration.
Represents a base class of a C++ class.
SourceManager & getSourceManager()
QualType getResultType() const
Returns the result type, adjusted for references.
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)
Returns the option controlling which C++ member functions will be considered for inlining.
pred_iterator pred_begin()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
unsigned getMaxTimesInlineLarge()
Returns the maximum times a large function could be inlined.
static CallInlinePolicy mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, AnalyzerOptions &Opts)
ProgramStateRef invalidateRegions(unsigned BlockCount, ProgramStateRef Orig=nullptr) const
Returns a new state with all argument regions invalidated.
virtual void enqueue(const WorkListUnit &U)=0
const BlockInvocationContext * getBlockInvocationContext(const LocationContext *parent, const BlockDecl *BD, const void *ContextData)
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
bool mayInlineCXXAllocator()
Returns whether or not allocator call may be considered for inlining.
AnalysisPurgeMode AnalysisPurgeOpt
Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailabl...
bool mayInlineCXXSharedPtrDtor()
Returns whether or not the destructor of C++ 'shared_ptr' may be considered for inlining.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
AnalysisDeclContext * getAnalysisDeclContext() const
Represents a call to a C++ constructor.
const LangOptions & getLangOpts() const
void processCallEnter(NodeBuilderContext &BC, CallEnter CE, ExplodedNode *Pred) override
Generate the entry node of the callee.
CallEventRef< T > cloneWithState(ProgramStateRef State) const
bool shouldInlineCall() const
ConstructionKind getConstructionKind() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...