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
425 !cast<BlockCall>(Call).isConversionFromLambda()) {
427 assert(BR &&
"If we have the block definition we should have its region");
435 const Expr *CallE = Call.getOriginExpr();
441 currBldrCtx->getBlock(),
449 State = State->enterStackFrame(Call, CalleeSFC);
452 if (
ExplodedNode *N = G.getNode(Loc, State,
false, &isNew)) {
453 N->addPredecessor(Pred, G);
455 Engine.getWorkList()->enqueue(N);
460 Bldr.takeNodes(Pred);
466 VisitedCallees->insert(D);
477 assert(ReplayState == CallE &&
"Backtracked to the wrong call.");
500 evalCall(dstCallEvaluated, *
I, *CallTemplate);
544 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
545 switch (Msg->getMethodFamily()) {
552 return State->BindExpr(E, LCtx, Msg->getReceiverSVal());
556 SVal ThisV =
C->getCXXThisVal();
560 ThisV = State->getSVal(ThisV.
castAs<
Loc>());
562 return State->BindExpr(E, LCtx, ThisV);
570 return State->BindExpr(E, LCtx, R);
615 if (Target && isa<ElementRegion>(Target))
624 if (isa<CXXNewExpr>(Parent))
644 if (!Target || !isa<DeclRegion>(Target))
661 const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion();
662 if (Target && isa<ElementRegion>(Target))
735 if (II->isStr(
"shared_ptr"))
749 if (CallEvent::isVariadic(CalleeADC->
getDecl()))
787 const CFG *CalleeCFG = CalleeADC->
getCFG();
803 bool ExprEngine::shouldInlineCall(
const CallEvent &Call,
const Decl *D,
816 if (isa<CXXDestructorCall>(Call)) {
817 if ((*currBldrCtx->getBlock())[currStmtIdx].getAs<CFGTemporaryDtor>())
831 Optional<bool> MayInline = Engine.FunctionSummaries->mayInline(D);
832 if (MayInline.hasValue()) {
833 if (!MayInline.getValue())
840 Engine.FunctionSummaries->markMayInline(D);
842 Engine.FunctionSummaries->markShouldNotInline(D);
854 assert(!MayInline.hasValue() || MayInline.getValue());
855 Engine.FunctionSummaries->markShouldNotInline(D);
860 const CFG *CalleeCFG = CalleeADC->
getCFG();
863 bool IsRecursive =
false;
864 unsigned StackDepth = 0;
872 if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
876 NumReachedInlineCountMax++;
880 if (HowToInline == Inline_Minimal &&
885 Engine.FunctionSummaries->bumpNumTimesInlined(D);
912 performTrivialCopy(Bldr, Pred, *Call);
919 const Expr *
E = Call->getOriginExpr();
922 if (InlinedFailedState) {
924 State = InlinedFailedState;
928 if (shouldInlineCall(*Call, D, Pred)) {
940 conservativeEvalCall(*Call, Bldr, Pred, State);
946 if (inlineCall(*Call, D, Bldr, Pred, State))
952 conservativeEvalCall(*Call, Bldr, Pred, State);
955 void ExprEngine::BifurcateCall(
const MemRegion *BifurReg,
964 const unsigned *BState =
965 State->get<DynamicDispatchBifurcationMap>(BifurReg);
968 if (*BState == DynamicDispatchModeInlined)
969 if (inlineCall(Call, D, Bldr, Pred, State))
974 conservativeEvalCall(Call, Bldr, Pred, State);
981 State->set<DynamicDispatchBifurcationMap>(BifurReg,
982 DynamicDispatchModeInlined);
983 inlineCall(Call, D, Bldr, Pred, IState);
986 State->set<DynamicDispatchBifurcationMap>(BifurReg,
987 DynamicDispatchModeConservative);
988 conservativeEvalCall(Call, Bldr, Pred, NoIState);
990 NumOfDynamicDispatchPathSplits++;
999 getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *
this);
1005 ei = dstPreVisit.
end(); it != ei; ++it) {
AnalysisDeclContextManager & getAnalysisDeclContextManager()
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
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)
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.
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
Generate the sequence of nodes that simulate the call exit and the post visit for CallExpr...
const StackFrameContext * getCalleeContext() const
This builder class is useful for generating nodes that resulted from visiting a statement.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
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.
IdentifierInfo * getAsIdentifierInfo() const
getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in this declaration name, or NULL if this declaration name isn't a simple identifier.
bool isStdNamespace() const
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)
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)
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()
Returns whether or not templated functions may be considered for inlining.
One of these records is kept for each identifier that is lexed.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
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 contains the context data for the function or method under analysis.
AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that that type refers to...
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.
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
BlockDataRegion - A region that represents a block instance.
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
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 CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
T * getAnalysis()
Return the specified analysis object, lazily running the analysis if necessary.
unsigned getMinCFGSizeTreatFunctionsAsLarge()
Returns the number of basic blocks a function needs to have to be considered large for the 'max-times...
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)
Returns true if the given function is the destructor of a class named "shared_ptr".
detail::InMemoryDirectory::const_iterator I
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)
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.
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
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.
Expr - This represents one expression.
const ProgramStateRef & getState() const
IPAKind getIPAMode()
Returns the inter-procedural analysis mode.
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
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.
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
DeclContext * getParent()
getParent - Returns the containing DeclContext.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
Base-class lookup callback that determines whether there exists a member with the given name...
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...
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
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.
While alive, includes the current analysis stack in a crash trace.
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
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.
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.
AnalyzerOptions & options
const Decl * getDecl() const
Refers to destructors (implicit or explicit).
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
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
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.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
SValBuilder & getSValBuilder()
StoreManager & getStoreManager()
const LocationContext * getLocationContext() const
DeclarationName - The name of a declaration.
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
detail::InMemoryDirectory::const_iterator E
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.
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
QualType getResultType() const
Returns the result type, adjusted for references.
QualType getCanonicalType() const
WorkList * getWorkList() const
static QualType getDeclaredResultType(const Decl *D)
Returns the result type of a function or method declaration.
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
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")
Represents a base class of a C++ class.
SourceManager & getSourceManager()
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.
bool isObjCObjectPointerType() const
CallEventRef< T > cloneWithState(ProgramStateRef State) const
pred_iterator pred_begin()
SVal getCXXThisVal() const
Returns the value of the implicit 'this' object.
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)
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.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
unsigned getNumBlockIDs() const
getNumBlockIDs - Returns the total number of BlockIDs allocated (which start at 0).
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