106f32e7eSjoerg //===- ExprEngine.h - Path-Sensitive Expression-Level Dataflow --*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg //  This file defines a meta-engine for path-sensitive dataflow analysis that
1006f32e7eSjoerg //  is built on CoreEngine, but provides the boilerplate to execute transfer
1106f32e7eSjoerg //  functions and build the ExplodedGraph at the expression level.
1206f32e7eSjoerg //
1306f32e7eSjoerg //===----------------------------------------------------------------------===//
1406f32e7eSjoerg 
1506f32e7eSjoerg #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
1606f32e7eSjoerg #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
1706f32e7eSjoerg 
1806f32e7eSjoerg #include "clang/AST/Expr.h"
1906f32e7eSjoerg #include "clang/AST/Type.h"
2006f32e7eSjoerg #include "clang/Analysis/CFG.h"
2106f32e7eSjoerg #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
2206f32e7eSjoerg #include "clang/Analysis/ProgramPoint.h"
2306f32e7eSjoerg #include "clang/Basic/LLVM.h"
24*13fbcb42Sjoerg #include "clang/StaticAnalyzer/Core/CheckerManager.h"
2506f32e7eSjoerg #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
2606f32e7eSjoerg #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
2706f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
2806f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
2906f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
3006f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
3106f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
3206f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
33*13fbcb42Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
3406f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
3506f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
3606f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
3706f32e7eSjoerg #include "llvm/ADT/ArrayRef.h"
3806f32e7eSjoerg #include <cassert>
3906f32e7eSjoerg #include <utility>
4006f32e7eSjoerg 
4106f32e7eSjoerg namespace clang {
4206f32e7eSjoerg 
4306f32e7eSjoerg class AnalysisDeclContextManager;
4406f32e7eSjoerg class AnalyzerOptions;
4506f32e7eSjoerg class ASTContext;
46*13fbcb42Sjoerg class CFGBlock;
47*13fbcb42Sjoerg class CFGElement;
4806f32e7eSjoerg class ConstructionContext;
4906f32e7eSjoerg class CXXBindTemporaryExpr;
5006f32e7eSjoerg class CXXCatchStmt;
5106f32e7eSjoerg class CXXConstructExpr;
5206f32e7eSjoerg class CXXDeleteExpr;
5306f32e7eSjoerg class CXXNewExpr;
5406f32e7eSjoerg class CXXThisExpr;
5506f32e7eSjoerg class Decl;
5606f32e7eSjoerg class DeclStmt;
5706f32e7eSjoerg class GCCAsmStmt;
5806f32e7eSjoerg class LambdaExpr;
5906f32e7eSjoerg class LocationContext;
6006f32e7eSjoerg class MaterializeTemporaryExpr;
6106f32e7eSjoerg class MSAsmStmt;
6206f32e7eSjoerg class NamedDecl;
6306f32e7eSjoerg class ObjCAtSynchronizedStmt;
6406f32e7eSjoerg class ObjCForCollectionStmt;
6506f32e7eSjoerg class ObjCIvarRefExpr;
6606f32e7eSjoerg class ObjCMessageExpr;
6706f32e7eSjoerg class ReturnStmt;
6806f32e7eSjoerg class Stmt;
6906f32e7eSjoerg 
7006f32e7eSjoerg namespace cross_tu {
7106f32e7eSjoerg 
7206f32e7eSjoerg class CrossTranslationUnitContext;
7306f32e7eSjoerg 
7406f32e7eSjoerg } // namespace cross_tu
7506f32e7eSjoerg 
7606f32e7eSjoerg namespace ento {
7706f32e7eSjoerg 
78*13fbcb42Sjoerg class AnalysisManager;
7906f32e7eSjoerg class BasicValueFactory;
80*13fbcb42Sjoerg class BlockCounter;
81*13fbcb42Sjoerg class BranchNodeBuilder;
8206f32e7eSjoerg class CallEvent;
8306f32e7eSjoerg class CheckerManager;
8406f32e7eSjoerg class ConstraintManager;
8506f32e7eSjoerg class CXXTempObjectRegion;
86*13fbcb42Sjoerg class EndOfFunctionNodeBuilder;
87*13fbcb42Sjoerg class ExplodedNodeSet;
88*13fbcb42Sjoerg class ExplodedNode;
89*13fbcb42Sjoerg class IndirectGotoNodeBuilder;
9006f32e7eSjoerg class MemRegion;
91*13fbcb42Sjoerg struct NodeBuilderContext;
92*13fbcb42Sjoerg class NodeBuilderWithSinks;
93*13fbcb42Sjoerg class ProgramState;
94*13fbcb42Sjoerg class ProgramStateManager;
9506f32e7eSjoerg class RegionAndSymbolInvalidationTraits;
9606f32e7eSjoerg class SymbolManager;
97*13fbcb42Sjoerg class SwitchNodeBuilder;
9806f32e7eSjoerg 
9906f32e7eSjoerg /// Hints for figuring out of a call should be inlined during evalCall().
10006f32e7eSjoerg struct EvalCallOptions {
10106f32e7eSjoerg   /// This call is a constructor or a destructor for which we do not currently
10206f32e7eSjoerg   /// compute the this-region correctly.
10306f32e7eSjoerg   bool IsCtorOrDtorWithImproperlyModeledTargetRegion = false;
10406f32e7eSjoerg 
10506f32e7eSjoerg   /// This call is a constructor or a destructor for a single element within
10606f32e7eSjoerg   /// an array, a part of array construction or destruction.
10706f32e7eSjoerg   bool IsArrayCtorOrDtor = false;
10806f32e7eSjoerg 
10906f32e7eSjoerg   /// This call is a constructor or a destructor of a temporary value.
11006f32e7eSjoerg   bool IsTemporaryCtorOrDtor = false;
11106f32e7eSjoerg 
11206f32e7eSjoerg   /// This call is a constructor for a temporary that is lifetime-extended
11306f32e7eSjoerg   /// by binding it to a reference-type field within an aggregate,
11406f32e7eSjoerg   /// for example 'A { const C &c; }; A a = { C() };'
11506f32e7eSjoerg   bool IsTemporaryLifetimeExtendedViaAggregate = false;
11606f32e7eSjoerg 
117*13fbcb42Sjoerg   /// This call is a pre-C++17 elidable constructor that we failed to elide
118*13fbcb42Sjoerg   /// because we failed to compute the target region into which
119*13fbcb42Sjoerg   /// this constructor would have been ultimately elided. Analysis that
120*13fbcb42Sjoerg   /// we perform in this case is still correct but it behaves differently,
121*13fbcb42Sjoerg   /// as if copy elision is disabled.
122*13fbcb42Sjoerg   bool IsElidableCtorThatHasNotBeenElided = false;
123*13fbcb42Sjoerg 
EvalCallOptionsEvalCallOptions12406f32e7eSjoerg   EvalCallOptions() {}
12506f32e7eSjoerg };
12606f32e7eSjoerg 
127*13fbcb42Sjoerg class ExprEngine {
128*13fbcb42Sjoerg   void anchor();
129*13fbcb42Sjoerg 
130*13fbcb42Sjoerg public:
131*13fbcb42Sjoerg   /// The modes of inlining, which override the default analysis-wide settings.
132*13fbcb42Sjoerg   enum InliningModes {
133*13fbcb42Sjoerg     /// Follow the default settings for inlining callees.
134*13fbcb42Sjoerg     Inline_Regular = 0,
135*13fbcb42Sjoerg 
136*13fbcb42Sjoerg     /// Do minimal inlining of callees.
137*13fbcb42Sjoerg     Inline_Minimal = 0x1
138*13fbcb42Sjoerg   };
139*13fbcb42Sjoerg 
14006f32e7eSjoerg private:
14106f32e7eSjoerg   cross_tu::CrossTranslationUnitContext &CTU;
14206f32e7eSjoerg 
14306f32e7eSjoerg   AnalysisManager &AMgr;
14406f32e7eSjoerg 
14506f32e7eSjoerg   AnalysisDeclContextManager &AnalysisDeclContexts;
14606f32e7eSjoerg 
14706f32e7eSjoerg   CoreEngine Engine;
14806f32e7eSjoerg 
14906f32e7eSjoerg   /// G - the simulation graph.
15006f32e7eSjoerg   ExplodedGraph &G;
15106f32e7eSjoerg 
15206f32e7eSjoerg   /// StateMgr - Object that manages the data for all created states.
15306f32e7eSjoerg   ProgramStateManager StateMgr;
15406f32e7eSjoerg 
15506f32e7eSjoerg   /// SymMgr - Object that manages the symbol information.
15606f32e7eSjoerg   SymbolManager &SymMgr;
15706f32e7eSjoerg 
15806f32e7eSjoerg   /// MRMgr - MemRegionManager object that creates memory regions.
15906f32e7eSjoerg   MemRegionManager &MRMgr;
16006f32e7eSjoerg 
16106f32e7eSjoerg   /// svalBuilder - SValBuilder object that creates SVals from expressions.
16206f32e7eSjoerg   SValBuilder &svalBuilder;
16306f32e7eSjoerg 
16406f32e7eSjoerg   unsigned int currStmtIdx = 0;
16506f32e7eSjoerg   const NodeBuilderContext *currBldrCtx = nullptr;
16606f32e7eSjoerg 
16706f32e7eSjoerg   /// Helper object to determine if an Objective-C message expression
16806f32e7eSjoerg   /// implicitly never returns.
16906f32e7eSjoerg   ObjCNoReturn ObjCNoRet;
17006f32e7eSjoerg 
17106f32e7eSjoerg   /// The BugReporter associated with this engine.  It is important that
17206f32e7eSjoerg   /// this object be placed at the very end of member variables so that its
17306f32e7eSjoerg   /// destructor is called before the rest of the ExprEngine is destroyed.
17406f32e7eSjoerg   PathSensitiveBugReporter BR;
17506f32e7eSjoerg 
17606f32e7eSjoerg   /// The functions which have been analyzed through inlining. This is owned by
17706f32e7eSjoerg   /// AnalysisConsumer. It can be null.
17806f32e7eSjoerg   SetOfConstDecls *VisitedCallees;
17906f32e7eSjoerg 
18006f32e7eSjoerg   /// The flag, which specifies the mode of inlining for the engine.
18106f32e7eSjoerg   InliningModes HowToInline;
18206f32e7eSjoerg 
18306f32e7eSjoerg public:
18406f32e7eSjoerg   ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr,
18506f32e7eSjoerg              SetOfConstDecls *VisitedCalleesIn,
18606f32e7eSjoerg              FunctionSummariesTy *FS, InliningModes HowToInlineIn);
18706f32e7eSjoerg 
188*13fbcb42Sjoerg   virtual ~ExprEngine() = default;
18906f32e7eSjoerg 
19006f32e7eSjoerg   /// Returns true if there is still simulation state on the worklist.
19106f32e7eSjoerg   bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
19206f32e7eSjoerg     return Engine.ExecuteWorkList(L, Steps, nullptr);
19306f32e7eSjoerg   }
19406f32e7eSjoerg 
19506f32e7eSjoerg   /// Execute the work list with an initial state. Nodes that reaches the exit
19606f32e7eSjoerg   /// of the function are added into the Dst set, which represent the exit
19706f32e7eSjoerg   /// state of the function call. Returns true if there is still simulation
19806f32e7eSjoerg   /// state on the worklist.
ExecuteWorkListWithInitialState(const LocationContext * L,unsigned Steps,ProgramStateRef InitState,ExplodedNodeSet & Dst)19906f32e7eSjoerg   bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
20006f32e7eSjoerg                                        ProgramStateRef InitState,
20106f32e7eSjoerg                                        ExplodedNodeSet &Dst) {
20206f32e7eSjoerg     return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
20306f32e7eSjoerg   }
20406f32e7eSjoerg 
20506f32e7eSjoerg   /// getContext - Return the ASTContext associated with this analysis.
getContext()20606f32e7eSjoerg   ASTContext &getContext() const { return AMgr.getASTContext(); }
20706f32e7eSjoerg 
getAnalysisManager()208*13fbcb42Sjoerg   AnalysisManager &getAnalysisManager() { return AMgr; }
20906f32e7eSjoerg 
getAnalysisDeclContextManager()21006f32e7eSjoerg   AnalysisDeclContextManager &getAnalysisDeclContextManager() {
21106f32e7eSjoerg     return AMgr.getAnalysisDeclContextManager();
21206f32e7eSjoerg   }
21306f32e7eSjoerg 
getCheckerManager()21406f32e7eSjoerg   CheckerManager &getCheckerManager() const {
21506f32e7eSjoerg     return *AMgr.getCheckerManager();
21606f32e7eSjoerg   }
21706f32e7eSjoerg 
getSValBuilder()21806f32e7eSjoerg   SValBuilder &getSValBuilder() { return svalBuilder; }
21906f32e7eSjoerg 
getBugReporter()22006f32e7eSjoerg   BugReporter &getBugReporter() { return BR; }
22106f32e7eSjoerg 
22206f32e7eSjoerg   cross_tu::CrossTranslationUnitContext *
getCrossTranslationUnitContext()223*13fbcb42Sjoerg   getCrossTranslationUnitContext() {
22406f32e7eSjoerg     return &CTU;
22506f32e7eSjoerg   }
22606f32e7eSjoerg 
getBuilderContext()22706f32e7eSjoerg   const NodeBuilderContext &getBuilderContext() {
22806f32e7eSjoerg     assert(currBldrCtx);
22906f32e7eSjoerg     return *currBldrCtx;
23006f32e7eSjoerg   }
23106f32e7eSjoerg 
23206f32e7eSjoerg   const Stmt *getStmt() const;
23306f32e7eSjoerg 
23406f32e7eSjoerg   void GenerateAutoTransition(ExplodedNode *N);
23506f32e7eSjoerg   void enqueueEndOfPath(ExplodedNodeSet &S);
23606f32e7eSjoerg   void GenerateCallExitNode(ExplodedNode *N);
23706f32e7eSjoerg 
23806f32e7eSjoerg 
23906f32e7eSjoerg   /// Dump graph to the specified filename.
24006f32e7eSjoerg   /// If filename is empty, generate a temporary one.
24106f32e7eSjoerg   /// \return The filename the graph is written into.
24206f32e7eSjoerg   std::string DumpGraph(bool trim = false, StringRef Filename="");
24306f32e7eSjoerg 
24406f32e7eSjoerg   /// Dump the graph consisting of the given nodes to a specified filename.
24506f32e7eSjoerg   /// Generate a temporary filename if it's not provided.
24606f32e7eSjoerg   /// \return The filename the graph is written into.
24706f32e7eSjoerg   std::string DumpGraph(ArrayRef<const ExplodedNode *> Nodes,
24806f32e7eSjoerg                         StringRef Filename = "");
24906f32e7eSjoerg 
25006f32e7eSjoerg   /// Visualize the ExplodedGraph created by executing the simulation.
25106f32e7eSjoerg   void ViewGraph(bool trim = false);
25206f32e7eSjoerg 
25306f32e7eSjoerg   /// Visualize a trimmed ExplodedGraph that only contains paths to the given
25406f32e7eSjoerg   /// nodes.
25506f32e7eSjoerg   void ViewGraph(ArrayRef<const ExplodedNode *> Nodes);
25606f32e7eSjoerg 
25706f32e7eSjoerg   /// getInitialState - Return the initial state used for the root vertex
25806f32e7eSjoerg   ///  in the ExplodedGraph.
259*13fbcb42Sjoerg   ProgramStateRef getInitialState(const LocationContext *InitLoc);
26006f32e7eSjoerg 
getGraph()26106f32e7eSjoerg   ExplodedGraph &getGraph() { return G; }
getGraph()26206f32e7eSjoerg   const ExplodedGraph &getGraph() const { return G; }
26306f32e7eSjoerg 
26406f32e7eSjoerg   /// Run the analyzer's garbage collection - remove dead symbols and
26506f32e7eSjoerg   /// bindings from the state.
26606f32e7eSjoerg   ///
26706f32e7eSjoerg   /// Checkers can participate in this process with two callbacks:
26806f32e7eSjoerg   /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation
26906f32e7eSjoerg   /// class for more information.
27006f32e7eSjoerg   ///
27106f32e7eSjoerg   /// \param Node The predecessor node, from which the processing should start.
27206f32e7eSjoerg   /// \param Out The returned set of output nodes.
27306f32e7eSjoerg   /// \param ReferenceStmt The statement which is about to be processed.
27406f32e7eSjoerg   ///        Everything needed for this statement should be considered live.
27506f32e7eSjoerg   ///        A null statement means that everything in child LocationContexts
27606f32e7eSjoerg   ///        is dead.
27706f32e7eSjoerg   /// \param LC The location context of the \p ReferenceStmt. A null location
27806f32e7eSjoerg   ///        context means that we have reached the end of analysis and that
27906f32e7eSjoerg   ///        all statements and local variables should be considered dead.
28006f32e7eSjoerg   /// \param DiagnosticStmt Used as a location for any warnings that should
28106f32e7eSjoerg   ///        occur while removing the dead (e.g. leaks). By default, the
28206f32e7eSjoerg   ///        \p ReferenceStmt is used.
28306f32e7eSjoerg   /// \param K Denotes whether this is a pre- or post-statement purge. This
28406f32e7eSjoerg   ///        must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
28506f32e7eSjoerg   ///        entire location context is being cleared, in which case the
28606f32e7eSjoerg   ///        \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
28706f32e7eSjoerg   ///        it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
28806f32e7eSjoerg   ///        and \p ReferenceStmt must be valid (non-null).
28906f32e7eSjoerg   void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
29006f32e7eSjoerg             const Stmt *ReferenceStmt, const LocationContext *LC,
29106f32e7eSjoerg             const Stmt *DiagnosticStmt = nullptr,
29206f32e7eSjoerg             ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
29306f32e7eSjoerg 
29406f32e7eSjoerg   /// processCFGElement - Called by CoreEngine. Used to generate new successor
29506f32e7eSjoerg   ///  nodes by processing the 'effects' of a CFG element.
29606f32e7eSjoerg   void processCFGElement(const CFGElement E, ExplodedNode *Pred,
297*13fbcb42Sjoerg                          unsigned StmtIdx, NodeBuilderContext *Ctx);
29806f32e7eSjoerg 
29906f32e7eSjoerg   void ProcessStmt(const Stmt *S, ExplodedNode *Pred);
30006f32e7eSjoerg 
30106f32e7eSjoerg   void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred);
30206f32e7eSjoerg 
30306f32e7eSjoerg   void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
30406f32e7eSjoerg 
30506f32e7eSjoerg   void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
30606f32e7eSjoerg 
30706f32e7eSjoerg   void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred);
30806f32e7eSjoerg 
30906f32e7eSjoerg   void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
31006f32e7eSjoerg                                ExplodedNode *Pred, ExplodedNodeSet &Dst);
31106f32e7eSjoerg   void ProcessDeleteDtor(const CFGDeleteDtor D,
31206f32e7eSjoerg                          ExplodedNode *Pred, ExplodedNodeSet &Dst);
31306f32e7eSjoerg   void ProcessBaseDtor(const CFGBaseDtor D,
31406f32e7eSjoerg                        ExplodedNode *Pred, ExplodedNodeSet &Dst);
31506f32e7eSjoerg   void ProcessMemberDtor(const CFGMemberDtor D,
31606f32e7eSjoerg                          ExplodedNode *Pred, ExplodedNodeSet &Dst);
31706f32e7eSjoerg   void ProcessTemporaryDtor(const CFGTemporaryDtor D,
31806f32e7eSjoerg                             ExplodedNode *Pred, ExplodedNodeSet &Dst);
31906f32e7eSjoerg 
32006f32e7eSjoerg   /// Called by CoreEngine when processing the entrance of a CFGBlock.
32106f32e7eSjoerg   void processCFGBlockEntrance(const BlockEdge &L,
32206f32e7eSjoerg                                NodeBuilderWithSinks &nodeBuilder,
323*13fbcb42Sjoerg                                ExplodedNode *Pred);
32406f32e7eSjoerg 
32506f32e7eSjoerg   /// ProcessBranch - Called by CoreEngine.  Used to generate successor
32606f32e7eSjoerg   ///  nodes by processing the 'effects' of a branch condition.
32706f32e7eSjoerg   void processBranch(const Stmt *Condition,
32806f32e7eSjoerg                      NodeBuilderContext& BuilderCtx,
32906f32e7eSjoerg                      ExplodedNode *Pred,
33006f32e7eSjoerg                      ExplodedNodeSet &Dst,
33106f32e7eSjoerg                      const CFGBlock *DstT,
332*13fbcb42Sjoerg                      const CFGBlock *DstF);
33306f32e7eSjoerg 
33406f32e7eSjoerg   /// Called by CoreEngine.
33506f32e7eSjoerg   /// Used to generate successor nodes for temporary destructors depending
33606f32e7eSjoerg   /// on whether the corresponding constructor was visited.
33706f32e7eSjoerg   void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
33806f32e7eSjoerg                                      NodeBuilderContext &BldCtx,
33906f32e7eSjoerg                                      ExplodedNode *Pred, ExplodedNodeSet &Dst,
34006f32e7eSjoerg                                      const CFGBlock *DstT,
341*13fbcb42Sjoerg                                      const CFGBlock *DstF);
34206f32e7eSjoerg 
34306f32e7eSjoerg   /// Called by CoreEngine.  Used to processing branching behavior
34406f32e7eSjoerg   /// at static initializers.
34506f32e7eSjoerg   void processStaticInitializer(const DeclStmt *DS,
34606f32e7eSjoerg                                 NodeBuilderContext& BuilderCtx,
34706f32e7eSjoerg                                 ExplodedNode *Pred,
34806f32e7eSjoerg                                 ExplodedNodeSet &Dst,
34906f32e7eSjoerg                                 const CFGBlock *DstT,
350*13fbcb42Sjoerg                                 const CFGBlock *DstF);
35106f32e7eSjoerg 
35206f32e7eSjoerg   /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
35306f32e7eSjoerg   ///  nodes by processing the 'effects' of a computed goto jump.
354*13fbcb42Sjoerg   void processIndirectGoto(IndirectGotoNodeBuilder& builder);
35506f32e7eSjoerg 
35606f32e7eSjoerg   /// ProcessSwitch - Called by CoreEngine.  Used to generate successor
35706f32e7eSjoerg   ///  nodes by processing the 'effects' of a switch statement.
358*13fbcb42Sjoerg   void processSwitch(SwitchNodeBuilder& builder);
35906f32e7eSjoerg 
36006f32e7eSjoerg   /// Called by CoreEngine.  Used to notify checkers that processing a
36106f32e7eSjoerg   /// function has begun. Called for both inlined and and top-level functions.
36206f32e7eSjoerg   void processBeginOfFunction(NodeBuilderContext &BC,
36306f32e7eSjoerg                               ExplodedNode *Pred, ExplodedNodeSet &Dst,
364*13fbcb42Sjoerg                               const BlockEdge &L);
36506f32e7eSjoerg 
36606f32e7eSjoerg   /// Called by CoreEngine.  Used to notify checkers that processing a
36706f32e7eSjoerg   /// function has ended. Called for both inlined and and top-level functions.
36806f32e7eSjoerg   void processEndOfFunction(NodeBuilderContext& BC,
36906f32e7eSjoerg                             ExplodedNode *Pred,
370*13fbcb42Sjoerg                             const ReturnStmt *RS = nullptr);
37106f32e7eSjoerg 
37206f32e7eSjoerg   /// Remove dead bindings/symbols before exiting a function.
37306f32e7eSjoerg   void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
37406f32e7eSjoerg                                  ExplodedNode *Pred,
37506f32e7eSjoerg                                  ExplodedNodeSet &Dst);
37606f32e7eSjoerg 
37706f32e7eSjoerg   /// Generate the entry node of the callee.
37806f32e7eSjoerg   void processCallEnter(NodeBuilderContext& BC, CallEnter CE,
379*13fbcb42Sjoerg                         ExplodedNode *Pred);
38006f32e7eSjoerg 
38106f32e7eSjoerg   /// Generate the sequence of nodes that simulate the call exit and the post
38206f32e7eSjoerg   /// visit for CallExpr.
383*13fbcb42Sjoerg   void processCallExit(ExplodedNode *Pred);
38406f32e7eSjoerg 
38506f32e7eSjoerg   /// Called by CoreEngine when the analysis worklist has terminated.
386*13fbcb42Sjoerg   void processEndWorklist();
38706f32e7eSjoerg 
38806f32e7eSjoerg   /// evalAssume - Callback function invoked by the ConstraintManager when
38906f32e7eSjoerg   ///  making assumptions about state values.
39006f32e7eSjoerg   ProgramStateRef processAssume(ProgramStateRef state, SVal cond,
391*13fbcb42Sjoerg                                 bool assumption);
39206f32e7eSjoerg 
39306f32e7eSjoerg   /// processRegionChanges - Called by ProgramStateManager whenever a change is made
39406f32e7eSjoerg   ///  to the store. Used to update checkers that track region values.
39506f32e7eSjoerg   ProgramStateRef
39606f32e7eSjoerg   processRegionChanges(ProgramStateRef state,
39706f32e7eSjoerg                        const InvalidatedSymbols *invalidated,
39806f32e7eSjoerg                        ArrayRef<const MemRegion *> ExplicitRegions,
39906f32e7eSjoerg                        ArrayRef<const MemRegion *> Regions,
40006f32e7eSjoerg                        const LocationContext *LCtx,
401*13fbcb42Sjoerg                        const CallEvent *Call);
402*13fbcb42Sjoerg 
403*13fbcb42Sjoerg   inline ProgramStateRef
processRegionChange(ProgramStateRef state,const MemRegion * MR,const LocationContext * LCtx)404*13fbcb42Sjoerg   processRegionChange(ProgramStateRef state,
405*13fbcb42Sjoerg                       const MemRegion* MR,
406*13fbcb42Sjoerg                       const LocationContext *LCtx) {
407*13fbcb42Sjoerg     return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr);
408*13fbcb42Sjoerg   }
40906f32e7eSjoerg 
41006f32e7eSjoerg   /// printJson - Called by ProgramStateManager to print checker-specific data.
41106f32e7eSjoerg   void printJson(raw_ostream &Out, ProgramStateRef State,
41206f32e7eSjoerg                  const LocationContext *LCtx, const char *NL,
413*13fbcb42Sjoerg                  unsigned int Space, bool IsDot) const;
41406f32e7eSjoerg 
getStateManager()415*13fbcb42Sjoerg   ProgramStateManager &getStateManager() { return StateMgr; }
41606f32e7eSjoerg 
getStoreManager()41706f32e7eSjoerg   StoreManager &getStoreManager() { return StateMgr.getStoreManager(); }
41806f32e7eSjoerg 
getConstraintManager()41906f32e7eSjoerg   ConstraintManager &getConstraintManager() {
42006f32e7eSjoerg     return StateMgr.getConstraintManager();
42106f32e7eSjoerg   }
42206f32e7eSjoerg 
42306f32e7eSjoerg   // FIXME: Remove when we migrate over to just using SValBuilder.
getBasicVals()42406f32e7eSjoerg   BasicValueFactory &getBasicVals() {
42506f32e7eSjoerg     return StateMgr.getBasicVals();
42606f32e7eSjoerg   }
42706f32e7eSjoerg 
getSymbolManager()42806f32e7eSjoerg   SymbolManager &getSymbolManager() { return SymMgr; }
getRegionManager()42906f32e7eSjoerg   MemRegionManager &getRegionManager() { return MRMgr; }
43006f32e7eSjoerg 
getNoteTags()43106f32e7eSjoerg   NoteTag::Factory &getNoteTags() { return Engine.getNoteTags(); }
43206f32e7eSjoerg 
43306f32e7eSjoerg 
43406f32e7eSjoerg   // Functions for external checking of whether we have unfinished work
wasBlocksExhausted()43506f32e7eSjoerg   bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
hasEmptyWorkList()43606f32e7eSjoerg   bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
hasWorkRemaining()43706f32e7eSjoerg   bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); }
43806f32e7eSjoerg 
getCoreEngine()43906f32e7eSjoerg   const CoreEngine &getCoreEngine() const { return Engine; }
44006f32e7eSjoerg 
44106f32e7eSjoerg public:
44206f32e7eSjoerg   /// Visit - Transfer function logic for all statements.  Dispatches to
44306f32e7eSjoerg   ///  other functions that handle specific kinds of statements.
44406f32e7eSjoerg   void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst);
44506f32e7eSjoerg 
44606f32e7eSjoerg   /// VisitArraySubscriptExpr - Transfer function for array accesses.
44706f32e7eSjoerg   void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex,
44806f32e7eSjoerg                                ExplodedNode *Pred,
44906f32e7eSjoerg                                ExplodedNodeSet &Dst);
45006f32e7eSjoerg 
45106f32e7eSjoerg   /// VisitGCCAsmStmt - Transfer function logic for inline asm.
45206f32e7eSjoerg   void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
45306f32e7eSjoerg                        ExplodedNodeSet &Dst);
45406f32e7eSjoerg 
45506f32e7eSjoerg   /// VisitMSAsmStmt - Transfer function logic for MS inline asm.
45606f32e7eSjoerg   void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
45706f32e7eSjoerg                       ExplodedNodeSet &Dst);
45806f32e7eSjoerg 
45906f32e7eSjoerg   /// VisitBlockExpr - Transfer function logic for BlockExprs.
46006f32e7eSjoerg   void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
46106f32e7eSjoerg                       ExplodedNodeSet &Dst);
46206f32e7eSjoerg 
46306f32e7eSjoerg   /// VisitLambdaExpr - Transfer function logic for LambdaExprs.
46406f32e7eSjoerg   void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
46506f32e7eSjoerg                        ExplodedNodeSet &Dst);
46606f32e7eSjoerg 
46706f32e7eSjoerg   /// VisitBinaryOperator - Transfer function logic for binary operators.
46806f32e7eSjoerg   void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,
46906f32e7eSjoerg                            ExplodedNodeSet &Dst);
47006f32e7eSjoerg 
47106f32e7eSjoerg 
47206f32e7eSjoerg   /// VisitCall - Transfer function for function calls.
47306f32e7eSjoerg   void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
47406f32e7eSjoerg                      ExplodedNodeSet &Dst);
47506f32e7eSjoerg 
47606f32e7eSjoerg   /// VisitCast - Transfer function logic for all casts (implicit and explicit).
47706f32e7eSjoerg   void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
47806f32e7eSjoerg                  ExplodedNodeSet &Dst);
47906f32e7eSjoerg 
48006f32e7eSjoerg   /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
48106f32e7eSjoerg   void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
48206f32e7eSjoerg                                 ExplodedNode *Pred, ExplodedNodeSet &Dst);
48306f32e7eSjoerg 
48406f32e7eSjoerg   /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
48506f32e7eSjoerg   void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D,
48606f32e7eSjoerg                               ExplodedNode *Pred, ExplodedNodeSet &Dst);
48706f32e7eSjoerg 
48806f32e7eSjoerg   /// VisitDeclStmt - Transfer function logic for DeclStmts.
48906f32e7eSjoerg   void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
49006f32e7eSjoerg                      ExplodedNodeSet &Dst);
49106f32e7eSjoerg 
49206f32e7eSjoerg   /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
49306f32e7eSjoerg   void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,
49406f32e7eSjoerg                         ExplodedNode *Pred, ExplodedNodeSet &Dst);
49506f32e7eSjoerg 
49606f32e7eSjoerg   void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
49706f32e7eSjoerg                          ExplodedNodeSet &Dst);
49806f32e7eSjoerg 
49906f32e7eSjoerg   /// VisitLogicalExpr - Transfer function logic for '&&', '||'
50006f32e7eSjoerg   void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
50106f32e7eSjoerg                         ExplodedNodeSet &Dst);
50206f32e7eSjoerg 
50306f32e7eSjoerg   /// VisitMemberExpr - Transfer function for member expressions.
50406f32e7eSjoerg   void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
50506f32e7eSjoerg                        ExplodedNodeSet &Dst);
50606f32e7eSjoerg 
50706f32e7eSjoerg   /// VisitAtomicExpr - Transfer function for builtin atomic expressions
50806f32e7eSjoerg   void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred,
50906f32e7eSjoerg                        ExplodedNodeSet &Dst);
51006f32e7eSjoerg 
51106f32e7eSjoerg   /// Transfer function logic for ObjCAtSynchronizedStmts.
51206f32e7eSjoerg   void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
51306f32e7eSjoerg                                    ExplodedNode *Pred, ExplodedNodeSet &Dst);
51406f32e7eSjoerg 
51506f32e7eSjoerg   /// Transfer function logic for computing the lvalue of an Objective-C ivar.
51606f32e7eSjoerg   void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred,
51706f32e7eSjoerg                                 ExplodedNodeSet &Dst);
51806f32e7eSjoerg 
51906f32e7eSjoerg   /// VisitObjCForCollectionStmt - Transfer function logic for
52006f32e7eSjoerg   ///  ObjCForCollectionStmt.
52106f32e7eSjoerg   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
52206f32e7eSjoerg                                   ExplodedNode *Pred, ExplodedNodeSet &Dst);
52306f32e7eSjoerg 
52406f32e7eSjoerg   void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,
52506f32e7eSjoerg                         ExplodedNodeSet &Dst);
52606f32e7eSjoerg 
52706f32e7eSjoerg   /// VisitReturnStmt - Transfer function logic for return statements.
52806f32e7eSjoerg   void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,
52906f32e7eSjoerg                        ExplodedNodeSet &Dst);
53006f32e7eSjoerg 
53106f32e7eSjoerg   /// VisitOffsetOfExpr - Transfer function for offsetof.
53206f32e7eSjoerg   void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred,
53306f32e7eSjoerg                          ExplodedNodeSet &Dst);
53406f32e7eSjoerg 
53506f32e7eSjoerg   /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
53606f32e7eSjoerg   void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
53706f32e7eSjoerg                                      ExplodedNode *Pred, ExplodedNodeSet &Dst);
53806f32e7eSjoerg 
53906f32e7eSjoerg   /// VisitUnaryOperator - Transfer function logic for unary operators.
54006f32e7eSjoerg   void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
54106f32e7eSjoerg                           ExplodedNodeSet &Dst);
54206f32e7eSjoerg 
54306f32e7eSjoerg   /// Handle ++ and -- (both pre- and post-increment).
54406f32e7eSjoerg   void VisitIncrementDecrementOperator(const UnaryOperator* U,
54506f32e7eSjoerg                                        ExplodedNode *Pred,
54606f32e7eSjoerg                                        ExplodedNodeSet &Dst);
54706f32e7eSjoerg 
54806f32e7eSjoerg   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
54906f32e7eSjoerg                                  ExplodedNodeSet &PreVisit,
55006f32e7eSjoerg                                  ExplodedNodeSet &Dst);
55106f32e7eSjoerg 
55206f32e7eSjoerg   void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
55306f32e7eSjoerg                          ExplodedNodeSet &Dst);
55406f32e7eSjoerg 
55506f32e7eSjoerg   void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
55606f32e7eSjoerg                         ExplodedNodeSet & Dst);
55706f32e7eSjoerg 
55806f32e7eSjoerg   void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred,
55906f32e7eSjoerg                              ExplodedNodeSet &Dst);
56006f32e7eSjoerg 
561*13fbcb42Sjoerg   void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E,
562*13fbcb42Sjoerg                                      ExplodedNode *Pred, ExplodedNodeSet &Dst);
563*13fbcb42Sjoerg 
56406f32e7eSjoerg   void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
56506f32e7eSjoerg                           const Stmt *S, bool IsBaseDtor,
56606f32e7eSjoerg                           ExplodedNode *Pred, ExplodedNodeSet &Dst,
56706f32e7eSjoerg                           EvalCallOptions &Options);
56806f32e7eSjoerg 
56906f32e7eSjoerg   void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
57006f32e7eSjoerg                                 ExplodedNode *Pred,
57106f32e7eSjoerg                                 ExplodedNodeSet &Dst);
57206f32e7eSjoerg 
57306f32e7eSjoerg   void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
57406f32e7eSjoerg                        ExplodedNodeSet &Dst);
57506f32e7eSjoerg 
57606f32e7eSjoerg   void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
57706f32e7eSjoerg                           ExplodedNodeSet &Dst);
57806f32e7eSjoerg 
57906f32e7eSjoerg   /// Create a C++ temporary object for an rvalue.
58006f32e7eSjoerg   void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
58106f32e7eSjoerg                                 ExplodedNode *Pred,
58206f32e7eSjoerg                                 ExplodedNodeSet &Dst);
58306f32e7eSjoerg 
58406f32e7eSjoerg   /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic
58506f32e7eSjoerg   ///  expressions of the form 'x != 0' and generate new nodes (stored in Dst)
58606f32e7eSjoerg   ///  with those assumptions.
58706f32e7eSjoerg   void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
58806f32e7eSjoerg                          const Expr *Ex);
58906f32e7eSjoerg 
59006f32e7eSjoerg   static std::pair<const ProgramPointTag *, const ProgramPointTag *>
59106f32e7eSjoerg     geteagerlyAssumeBinOpBifurcationTags();
59206f32e7eSjoerg 
evalMinus(SVal X)59306f32e7eSjoerg   SVal evalMinus(SVal X) {
59406f32e7eSjoerg     return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X;
59506f32e7eSjoerg   }
59606f32e7eSjoerg 
evalComplement(SVal X)59706f32e7eSjoerg   SVal evalComplement(SVal X) {
59806f32e7eSjoerg     return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X;
59906f32e7eSjoerg   }
60006f32e7eSjoerg 
60106f32e7eSjoerg   ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
60206f32e7eSjoerg                                       const LocationContext *LCtx, QualType T,
60306f32e7eSjoerg                                       QualType ExTy, const CastExpr *CastE,
60406f32e7eSjoerg                                       StmtNodeBuilder &Bldr,
60506f32e7eSjoerg                                       ExplodedNode *Pred);
60606f32e7eSjoerg 
60706f32e7eSjoerg   ProgramStateRef handleLVectorSplat(ProgramStateRef state,
60806f32e7eSjoerg                                      const LocationContext *LCtx,
60906f32e7eSjoerg                                      const CastExpr *CastE,
61006f32e7eSjoerg                                      StmtNodeBuilder &Bldr,
61106f32e7eSjoerg                                      ExplodedNode *Pred);
61206f32e7eSjoerg 
61306f32e7eSjoerg   void handleUOExtension(ExplodedNodeSet::iterator I,
61406f32e7eSjoerg                          const UnaryOperator* U,
61506f32e7eSjoerg                          StmtNodeBuilder &Bldr);
61606f32e7eSjoerg 
61706f32e7eSjoerg public:
evalBinOp(ProgramStateRef state,BinaryOperator::Opcode op,NonLoc L,NonLoc R,QualType T)61806f32e7eSjoerg   SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
61906f32e7eSjoerg                  NonLoc L, NonLoc R, QualType T) {
62006f32e7eSjoerg     return svalBuilder.evalBinOpNN(state, op, L, R, T);
62106f32e7eSjoerg   }
62206f32e7eSjoerg 
evalBinOp(ProgramStateRef state,BinaryOperator::Opcode op,NonLoc L,SVal R,QualType T)62306f32e7eSjoerg   SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
62406f32e7eSjoerg                  NonLoc L, SVal R, QualType T) {
62506f32e7eSjoerg     return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L,
62606f32e7eSjoerg                                                  R.castAs<NonLoc>(), T) : R;
62706f32e7eSjoerg   }
62806f32e7eSjoerg 
evalBinOp(ProgramStateRef ST,BinaryOperator::Opcode Op,SVal LHS,SVal RHS,QualType T)62906f32e7eSjoerg   SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
63006f32e7eSjoerg                  SVal LHS, SVal RHS, QualType T) {
63106f32e7eSjoerg     return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
63206f32e7eSjoerg   }
63306f32e7eSjoerg 
63406f32e7eSjoerg   /// By looking at a certain item that may be potentially part of an object's
63506f32e7eSjoerg   /// ConstructionContext, retrieve such object's location. A particular
63606f32e7eSjoerg   /// statement can be transparently passed as \p Item in most cases.
63706f32e7eSjoerg   static Optional<SVal>
63806f32e7eSjoerg   getObjectUnderConstruction(ProgramStateRef State,
63906f32e7eSjoerg                              const ConstructionContextItem &Item,
64006f32e7eSjoerg                              const LocationContext *LC);
64106f32e7eSjoerg 
64206f32e7eSjoerg   /// Call PointerEscape callback when a value escapes as a result of bind.
643*13fbcb42Sjoerg   ProgramStateRef processPointerEscapedOnBind(
644*13fbcb42Sjoerg       ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,
645*13fbcb42Sjoerg       const LocationContext *LCtx, PointerEscapeKind Kind,
646*13fbcb42Sjoerg       const CallEvent *Call);
647*13fbcb42Sjoerg 
64806f32e7eSjoerg   /// Call PointerEscape callback when a value escapes as a result of
64906f32e7eSjoerg   /// region invalidation.
65006f32e7eSjoerg   /// \param[in] ITraits Specifies invalidation traits for regions/symbols.
65106f32e7eSjoerg   ProgramStateRef notifyCheckersOfPointerEscape(
65206f32e7eSjoerg                            ProgramStateRef State,
65306f32e7eSjoerg                            const InvalidatedSymbols *Invalidated,
65406f32e7eSjoerg                            ArrayRef<const MemRegion *> ExplicitRegions,
65506f32e7eSjoerg                            const CallEvent *Call,
656*13fbcb42Sjoerg                            RegionAndSymbolInvalidationTraits &ITraits);
657*13fbcb42Sjoerg 
658*13fbcb42Sjoerg private:
659*13fbcb42Sjoerg   /// evalBind - Handle the semantics of binding a value to a specific location.
660*13fbcb42Sjoerg   ///  This method is used by evalStore, VisitDeclStmt, and others.
661*13fbcb42Sjoerg   void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
662*13fbcb42Sjoerg                 SVal location, SVal Val, bool atDeclInit = false,
663*13fbcb42Sjoerg                 const ProgramPoint *PP = nullptr);
664*13fbcb42Sjoerg 
665*13fbcb42Sjoerg   ProgramStateRef
666*13fbcb42Sjoerg   processPointerEscapedOnBind(ProgramStateRef State,
667*13fbcb42Sjoerg                               SVal Loc, SVal Val,
668*13fbcb42Sjoerg                               const LocationContext *LCtx);
66906f32e7eSjoerg 
67006f32e7eSjoerg   /// A simple wrapper when you only need to notify checkers of pointer-escape
671*13fbcb42Sjoerg   /// of some values.
672*13fbcb42Sjoerg   ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef<SVal> Vs,
673*13fbcb42Sjoerg                                PointerEscapeKind K,
674*13fbcb42Sjoerg                                const CallEvent *Call = nullptr) const;
67506f32e7eSjoerg 
67606f32e7eSjoerg public:
67706f32e7eSjoerg   // FIXME: 'tag' should be removed, and a LocationContext should be used
67806f32e7eSjoerg   // instead.
67906f32e7eSjoerg   // FIXME: Comment on the meaning of the arguments, when 'St' may not
68006f32e7eSjoerg   // be the same as Pred->state, and when 'location' may not be the
68106f32e7eSjoerg   // same as state->getLValue(Ex).
68206f32e7eSjoerg   /// Simulate a read of the result of Ex.
68306f32e7eSjoerg   void evalLoad(ExplodedNodeSet &Dst,
68406f32e7eSjoerg                 const Expr *NodeEx,  /* Eventually will be a CFGStmt */
68506f32e7eSjoerg                 const Expr *BoundExpr,
68606f32e7eSjoerg                 ExplodedNode *Pred,
68706f32e7eSjoerg                 ProgramStateRef St,
68806f32e7eSjoerg                 SVal location,
68906f32e7eSjoerg                 const ProgramPointTag *tag = nullptr,
69006f32e7eSjoerg                 QualType LoadTy = QualType());
69106f32e7eSjoerg 
69206f32e7eSjoerg   // FIXME: 'tag' should be removed, and a LocationContext should be used
69306f32e7eSjoerg   // instead.
69406f32e7eSjoerg   void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
69506f32e7eSjoerg                  ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
69606f32e7eSjoerg                  const ProgramPointTag *tag = nullptr);
69706f32e7eSjoerg 
69806f32e7eSjoerg   /// Return the CFG element corresponding to the worklist element
69906f32e7eSjoerg   /// that is currently being processed by ExprEngine.
getCurrentCFGElement()70006f32e7eSjoerg   CFGElement getCurrentCFGElement() {
70106f32e7eSjoerg     return (*currBldrCtx->getBlock())[currStmtIdx];
70206f32e7eSjoerg   }
70306f32e7eSjoerg 
70406f32e7eSjoerg   /// Create a new state in which the call return value is binded to the
70506f32e7eSjoerg   /// call origin expression.
70606f32e7eSjoerg   ProgramStateRef bindReturnValue(const CallEvent &Call,
70706f32e7eSjoerg                                   const LocationContext *LCtx,
70806f32e7eSjoerg                                   ProgramStateRef State);
70906f32e7eSjoerg 
71006f32e7eSjoerg   /// Evaluate a call, running pre- and post-call checkers and allowing checkers
71106f32e7eSjoerg   /// to be responsible for handling the evaluation of the call itself.
71206f32e7eSjoerg   void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
71306f32e7eSjoerg                 const CallEvent &Call);
71406f32e7eSjoerg 
71506f32e7eSjoerg   /// Default implementation of call evaluation.
71606f32e7eSjoerg   void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
71706f32e7eSjoerg                        const CallEvent &Call,
71806f32e7eSjoerg                        const EvalCallOptions &CallOpts = {});
71906f32e7eSjoerg 
720*13fbcb42Sjoerg   /// Find location of the object that is being constructed by a given
721*13fbcb42Sjoerg   /// constructor. This should ideally always succeed but due to not being
722*13fbcb42Sjoerg   /// fully implemented it sometimes indicates that it failed via its
723*13fbcb42Sjoerg   /// out-parameter CallOpts; in such cases a fake temporary region is
724*13fbcb42Sjoerg   /// returned, which is better than nothing but does not represent
725*13fbcb42Sjoerg   /// the actual behavior of the program.
726*13fbcb42Sjoerg   SVal computeObjectUnderConstruction(
727*13fbcb42Sjoerg       const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
728*13fbcb42Sjoerg       const ConstructionContext *CC, EvalCallOptions &CallOpts);
729*13fbcb42Sjoerg 
730*13fbcb42Sjoerg   /// Update the program state with all the path-sensitive information
731*13fbcb42Sjoerg   /// that's necessary to perform construction of an object with a given
732*13fbcb42Sjoerg   /// syntactic construction context. V and CallOpts have to be obtained from
733*13fbcb42Sjoerg   /// computeObjectUnderConstruction() invoked with the same set of
734*13fbcb42Sjoerg   /// the remaining arguments (E, State, LCtx, CC).
735*13fbcb42Sjoerg   ProgramStateRef updateObjectsUnderConstruction(
736*13fbcb42Sjoerg       SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
737*13fbcb42Sjoerg       const ConstructionContext *CC, const EvalCallOptions &CallOpts);
738*13fbcb42Sjoerg 
739*13fbcb42Sjoerg   /// A convenient wrapper around computeObjectUnderConstruction
740*13fbcb42Sjoerg   /// and updateObjectsUnderConstruction.
handleConstructionContext(const Expr * E,ProgramStateRef State,const LocationContext * LCtx,const ConstructionContext * CC,EvalCallOptions & CallOpts)741*13fbcb42Sjoerg   std::pair<ProgramStateRef, SVal> handleConstructionContext(
742*13fbcb42Sjoerg       const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
743*13fbcb42Sjoerg       const ConstructionContext *CC, EvalCallOptions &CallOpts) {
744*13fbcb42Sjoerg     SVal V = computeObjectUnderConstruction(E, State, LCtx, CC, CallOpts);
745*13fbcb42Sjoerg     return std::make_pair(
746*13fbcb42Sjoerg         updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts), V);
747*13fbcb42Sjoerg   }
748*13fbcb42Sjoerg 
74906f32e7eSjoerg private:
75006f32e7eSjoerg   ProgramStateRef finishArgumentConstruction(ProgramStateRef State,
75106f32e7eSjoerg                                              const CallEvent &Call);
75206f32e7eSjoerg   void finishArgumentConstruction(ExplodedNodeSet &Dst, ExplodedNode *Pred,
75306f32e7eSjoerg                                   const CallEvent &Call);
75406f32e7eSjoerg 
75506f32e7eSjoerg   void evalLoadCommon(ExplodedNodeSet &Dst,
75606f32e7eSjoerg                       const Expr *NodeEx,  /* Eventually will be a CFGStmt */
75706f32e7eSjoerg                       const Expr *BoundEx,
75806f32e7eSjoerg                       ExplodedNode *Pred,
75906f32e7eSjoerg                       ProgramStateRef St,
76006f32e7eSjoerg                       SVal location,
76106f32e7eSjoerg                       const ProgramPointTag *tag,
76206f32e7eSjoerg                       QualType LoadTy);
76306f32e7eSjoerg 
76406f32e7eSjoerg   void evalLocation(ExplodedNodeSet &Dst,
76506f32e7eSjoerg                     const Stmt *NodeEx, /* This will eventually be a CFGStmt */
76606f32e7eSjoerg                     const Stmt *BoundEx,
76706f32e7eSjoerg                     ExplodedNode *Pred,
76806f32e7eSjoerg                     ProgramStateRef St,
76906f32e7eSjoerg                     SVal location,
77006f32e7eSjoerg                     bool isLoad);
77106f32e7eSjoerg 
77206f32e7eSjoerg   /// Count the stack depth and determine if the call is recursive.
77306f32e7eSjoerg   void examineStackFrames(const Decl *D, const LocationContext *LCtx,
77406f32e7eSjoerg                           bool &IsRecursive, unsigned &StackDepth);
77506f32e7eSjoerg 
77606f32e7eSjoerg   enum CallInlinePolicy {
77706f32e7eSjoerg     CIP_Allowed,
77806f32e7eSjoerg     CIP_DisallowedOnce,
77906f32e7eSjoerg     CIP_DisallowedAlways
78006f32e7eSjoerg   };
78106f32e7eSjoerg 
78206f32e7eSjoerg   /// See if a particular call should be inlined, by only looking
78306f32e7eSjoerg   /// at the call event and the current state of analysis.
78406f32e7eSjoerg   CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
78506f32e7eSjoerg                                      const ExplodedNode *Pred,
78606f32e7eSjoerg                                      AnalyzerOptions &Opts,
78706f32e7eSjoerg                                      const EvalCallOptions &CallOpts);
78806f32e7eSjoerg 
78906f32e7eSjoerg   /// See if the given AnalysisDeclContext is built for a function that we
79006f32e7eSjoerg   /// should always inline simply because it's small enough.
79106f32e7eSjoerg   /// Apart from "small" functions, we also have "large" functions
79206f32e7eSjoerg   /// (cf. isLarge()), some of which are huge (cf. isHuge()), and we classify
79306f32e7eSjoerg   /// the remaining functions as "medium".
79406f32e7eSjoerg   bool isSmall(AnalysisDeclContext *ADC) const;
79506f32e7eSjoerg 
79606f32e7eSjoerg   /// See if the given AnalysisDeclContext is built for a function that we
79706f32e7eSjoerg   /// should inline carefully because it looks pretty large.
79806f32e7eSjoerg   bool isLarge(AnalysisDeclContext *ADC) const;
79906f32e7eSjoerg 
80006f32e7eSjoerg   /// See if the given AnalysisDeclContext is built for a function that we
80106f32e7eSjoerg   /// should never inline because it's legit gigantic.
80206f32e7eSjoerg   bool isHuge(AnalysisDeclContext *ADC) const;
80306f32e7eSjoerg 
80406f32e7eSjoerg   /// See if the given AnalysisDeclContext is built for a function that we
80506f32e7eSjoerg   /// should inline, just by looking at the declaration of the function.
80606f32e7eSjoerg   bool mayInlineDecl(AnalysisDeclContext *ADC) const;
80706f32e7eSjoerg 
80806f32e7eSjoerg   /// Checks our policies and decides weither the given call should be inlined.
80906f32e7eSjoerg   bool shouldInlineCall(const CallEvent &Call, const Decl *D,
81006f32e7eSjoerg                         const ExplodedNode *Pred,
81106f32e7eSjoerg                         const EvalCallOptions &CallOpts = {});
81206f32e7eSjoerg 
81306f32e7eSjoerg   bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
81406f32e7eSjoerg                   ExplodedNode *Pred, ProgramStateRef State);
81506f32e7eSjoerg 
81606f32e7eSjoerg   /// Conservatively evaluate call by invalidating regions and binding
81706f32e7eSjoerg   /// a conjured return value.
81806f32e7eSjoerg   void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
81906f32e7eSjoerg                             ExplodedNode *Pred, ProgramStateRef State);
82006f32e7eSjoerg 
82106f32e7eSjoerg   /// Either inline or process the call conservatively (or both), based
82206f32e7eSjoerg   /// on DynamicDispatchBifurcation data.
82306f32e7eSjoerg   void BifurcateCall(const MemRegion *BifurReg,
82406f32e7eSjoerg                      const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
82506f32e7eSjoerg                      ExplodedNode *Pred);
82606f32e7eSjoerg 
82706f32e7eSjoerg   bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
82806f32e7eSjoerg 
82906f32e7eSjoerg   /// Models a trivial copy or move constructor or trivial assignment operator
83006f32e7eSjoerg   /// call with a simple bind.
83106f32e7eSjoerg   void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
83206f32e7eSjoerg                           const CallEvent &Call);
83306f32e7eSjoerg 
83406f32e7eSjoerg   /// If the value of the given expression \p InitWithAdjustments is a NonLoc,
83506f32e7eSjoerg   /// copy it into a new temporary object region, and replace the value of the
83606f32e7eSjoerg   /// expression with that.
83706f32e7eSjoerg   ///
83806f32e7eSjoerg   /// If \p Result is provided, the new region will be bound to this expression
83906f32e7eSjoerg   /// instead of \p InitWithAdjustments.
84006f32e7eSjoerg   ///
84106f32e7eSjoerg   /// Returns the temporary region with adjustments into the optional
84206f32e7eSjoerg   /// OutRegionWithAdjustments out-parameter if a new region was indeed needed,
84306f32e7eSjoerg   /// otherwise sets it to nullptr.
84406f32e7eSjoerg   ProgramStateRef createTemporaryRegionIfNeeded(
84506f32e7eSjoerg       ProgramStateRef State, const LocationContext *LC,
84606f32e7eSjoerg       const Expr *InitWithAdjustments, const Expr *Result = nullptr,
84706f32e7eSjoerg       const SubRegion **OutRegionWithAdjustments = nullptr);
84806f32e7eSjoerg 
84906f32e7eSjoerg   /// Returns a region representing the first element of a (possibly
85006f32e7eSjoerg   /// multi-dimensional) array, for the purposes of element construction or
85106f32e7eSjoerg   /// destruction.
85206f32e7eSjoerg   ///
85306f32e7eSjoerg   /// On return, \p Ty will be set to the base type of the array.
85406f32e7eSjoerg   ///
85506f32e7eSjoerg   /// If the type is not an array type at all, the original value is returned.
85606f32e7eSjoerg   /// Otherwise the "IsArray" flag is set.
85706f32e7eSjoerg   static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
85806f32e7eSjoerg                                     QualType &Ty, bool &IsArray);
85906f32e7eSjoerg 
86006f32e7eSjoerg   /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
86106f32e7eSjoerg   /// block to find the constructor expression that directly constructed into
86206f32e7eSjoerg   /// the storage for this statement. Returns null if the constructor for this
86306f32e7eSjoerg   /// statement created a temporary object region rather than directly
86406f32e7eSjoerg   /// constructing into an existing region.
86506f32e7eSjoerg   const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
86606f32e7eSjoerg 
867*13fbcb42Sjoerg   /// Common code that handles either a CXXConstructExpr or a
868*13fbcb42Sjoerg   /// CXXInheritedCtorInitExpr.
869*13fbcb42Sjoerg   void handleConstructor(const Expr *E, ExplodedNode *Pred,
870*13fbcb42Sjoerg                          ExplodedNodeSet &Dst);
87106f32e7eSjoerg 
872*13fbcb42Sjoerg public:
873*13fbcb42Sjoerg   /// Note whether this loop has any more iteratios to model. These methods are
874*13fbcb42Sjoerg   /// essentially an interface for a GDM trait. Further reading in
875*13fbcb42Sjoerg   /// ExprEngine::VisitObjCForCollectionStmt().
876*13fbcb42Sjoerg   LLVM_NODISCARD static ProgramStateRef
877*13fbcb42Sjoerg   setWhetherHasMoreIteration(ProgramStateRef State,
878*13fbcb42Sjoerg                              const ObjCForCollectionStmt *O,
879*13fbcb42Sjoerg                              const LocationContext *LC, bool HasMoreIteraton);
880*13fbcb42Sjoerg 
881*13fbcb42Sjoerg   LLVM_NODISCARD static ProgramStateRef
882*13fbcb42Sjoerg   removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O,
883*13fbcb42Sjoerg                        const LocationContext *LC);
884*13fbcb42Sjoerg 
885*13fbcb42Sjoerg   LLVM_NODISCARD static bool hasMoreIteration(ProgramStateRef State,
886*13fbcb42Sjoerg                                               const ObjCForCollectionStmt *O,
887*13fbcb42Sjoerg                                               const LocationContext *LC);
888*13fbcb42Sjoerg private:
88906f32e7eSjoerg   /// Store the location of a C++ object corresponding to a statement
89006f32e7eSjoerg   /// until the statement is actually encountered. For example, if a DeclStmt
89106f32e7eSjoerg   /// has CXXConstructExpr as its initializer, the object would be considered
89206f32e7eSjoerg   /// to be "under construction" between CXXConstructExpr and DeclStmt.
89306f32e7eSjoerg   /// This allows, among other things, to keep bindings to variable's fields
89406f32e7eSjoerg   /// made within the constructor alive until its declaration actually
89506f32e7eSjoerg   /// goes into scope.
89606f32e7eSjoerg   static ProgramStateRef
89706f32e7eSjoerg   addObjectUnderConstruction(ProgramStateRef State,
89806f32e7eSjoerg                              const ConstructionContextItem &Item,
89906f32e7eSjoerg                              const LocationContext *LC, SVal V);
90006f32e7eSjoerg 
90106f32e7eSjoerg   /// Mark the object sa fully constructed, cleaning up the state trait
90206f32e7eSjoerg   /// that tracks objects under construction.
90306f32e7eSjoerg   static ProgramStateRef
90406f32e7eSjoerg   finishObjectConstruction(ProgramStateRef State,
90506f32e7eSjoerg                            const ConstructionContextItem &Item,
90606f32e7eSjoerg                            const LocationContext *LC);
90706f32e7eSjoerg 
90806f32e7eSjoerg   /// If the given expression corresponds to a temporary that was used for
90906f32e7eSjoerg   /// passing into an elidable copy/move constructor and that constructor
91006f32e7eSjoerg   /// was actually elided, track that we also need to elide the destructor.
91106f32e7eSjoerg   static ProgramStateRef elideDestructor(ProgramStateRef State,
91206f32e7eSjoerg                                          const CXXBindTemporaryExpr *BTE,
91306f32e7eSjoerg                                          const LocationContext *LC);
91406f32e7eSjoerg 
91506f32e7eSjoerg   /// Stop tracking the destructor that corresponds to an elided constructor.
91606f32e7eSjoerg   static ProgramStateRef
91706f32e7eSjoerg   cleanupElidedDestructor(ProgramStateRef State,
91806f32e7eSjoerg                           const CXXBindTemporaryExpr *BTE,
91906f32e7eSjoerg                           const LocationContext *LC);
92006f32e7eSjoerg 
92106f32e7eSjoerg   /// Returns true if the given expression corresponds to a temporary that
92206f32e7eSjoerg   /// was constructed for passing into an elidable copy/move constructor
92306f32e7eSjoerg   /// and that constructor was actually elided.
92406f32e7eSjoerg   static bool isDestructorElided(ProgramStateRef State,
92506f32e7eSjoerg                                  const CXXBindTemporaryExpr *BTE,
92606f32e7eSjoerg                                  const LocationContext *LC);
92706f32e7eSjoerg 
92806f32e7eSjoerg   /// Check if all objects under construction have been fully constructed
92906f32e7eSjoerg   /// for the given context range (including FromLC, not including ToLC).
93006f32e7eSjoerg   /// This is useful for assertions. Also checks if elided destructors
93106f32e7eSjoerg   /// were cleaned up.
93206f32e7eSjoerg   static bool areAllObjectsFullyConstructed(ProgramStateRef State,
93306f32e7eSjoerg                                             const LocationContext *FromLC,
93406f32e7eSjoerg                                             const LocationContext *ToLC);
93506f32e7eSjoerg };
93606f32e7eSjoerg 
93706f32e7eSjoerg /// Traits for storing the call processing policy inside GDM.
93806f32e7eSjoerg /// The GDM stores the corresponding CallExpr pointer.
93906f32e7eSjoerg // FIXME: This does not use the nice trait macros because it must be accessible
94006f32e7eSjoerg // from multiple translation units.
94106f32e7eSjoerg struct ReplayWithoutInlining{};
94206f32e7eSjoerg template <>
94306f32e7eSjoerg struct ProgramStateTrait<ReplayWithoutInlining> :
94406f32e7eSjoerg   public ProgramStatePartialTrait<const void*> {
94506f32e7eSjoerg   static void *GDMIndex();
94606f32e7eSjoerg };
94706f32e7eSjoerg 
94806f32e7eSjoerg } // namespace ento
94906f32e7eSjoerg 
95006f32e7eSjoerg } // namespace clang
95106f32e7eSjoerg 
95206f32e7eSjoerg #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
953