diff options
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 33 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/Checker.h | 8 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/GRCoreEngine.h | 70 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/GRExprEngine.h | 8 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/GRSubEngine.h | 8 | ||||
-rw-r--r-- | lib/Checker/CallInliner.cpp | 76 | ||||
-rw-r--r-- | lib/Checker/GRCoreEngine.cpp | 98 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 40 |
8 files changed, 75 insertions, 266 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index fb8d4d5ff5..332f9d384f 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -26,7 +26,6 @@ namespace clang { class LocationContext; -class FunctionDecl; class ProgramPoint { public: @@ -42,8 +41,6 @@ public: PostPurgeDeadSymbolsKind, PostStmtCustomKind, PostLValueKind, - CallEnterKind, - CallExitKind, MinPostStmtKind = PostStmtKind, MaxPostStmtKind = PostLValueKind }; @@ -311,36 +308,6 @@ public: } }; -class CallEnter : public StmtPoint { -public: - // CallEnter uses the caller's location context. - CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L) - : StmtPoint(S, fd, CallEnterKind, L, 0) {} - - const Stmt *getCallExpr() const { - return static_cast<const Stmt *>(getData1()); - } - - const FunctionDecl *getCallee() const { - return static_cast<const FunctionDecl *>(getData2()); - } - - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == CallEnterKind; - } -}; - -class CallExit : public StmtPoint { -public: - // CallExit uses the callee's location context. - CallExit(const Stmt *S, const LocationContext *L) - : StmtPoint(S, 0, CallExitKind, L, 0) {} - - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == CallExitKind; - } -}; - } // end namespace clang diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index 2401a72741..519c00ec59 100644 --- a/include/clang/Checker/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -155,14 +155,6 @@ public: Dst.Add(Pred); } - // Generate a node with a new program point different from the one that will - // be created by the GRStmtNodeBuilder. - void addTransition(const GRState *state, ProgramPoint Loc) { - ExplodedNode *N = B.generateNode(Loc, state, Pred); - if (N) - addTransition(N); - } - void EmitReport(BugReport *R) { Eng.getBugReporter().EmitReport(R); } diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index dd789cb735..6da45815f9 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -40,8 +40,6 @@ class GRCoreEngine { friend class GRIndirectGotoNodeBuilder; friend class GRSwitchNodeBuilder; friend class GREndPathNodeBuilder; - friend class GRCallEnterNodeBuilder; - friend class GRCallExitNodeBuilder; GRSubEngine& SubEngine; @@ -69,9 +67,6 @@ class GRCoreEngine { void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B, ExplodedNode* Pred); - void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, - unsigned Index, ExplodedNode *Pred); - void HandleCallExit(const CallExit &L, ExplodedNode *Pred); /// Get the initial state from the subengine. const GRState* getInitialState(const LocationContext *InitLoc) { @@ -95,9 +90,6 @@ class GRCoreEngine { void ProcessSwitch(GRSwitchNodeBuilder& Builder); - void ProcessCallEnter(GRCallEnterNodeBuilder &Builder); - void ProcessCallExit(GRCallExitNodeBuilder &Builder); - private: GRCoreEngine(const GRCoreEngine&); // Do not implement. GRCoreEngine& operator=(const GRCoreEngine&); @@ -202,12 +194,6 @@ public: return generateNode(S, St, Pred, PointKind); } - ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State, - ExplodedNode* Pred) { - HasGeneratedNode = true; - return generateNodeInternal(PP, State, Pred); - } - ExplodedNode* generateNodeInternal(const ProgramPoint &PP, const GRState* State, ExplodedNode* Pred); @@ -445,8 +431,6 @@ public: ExplodedNode* generateNode(const GRState* State, const void *tag = 0, ExplodedNode *P = 0); - void GenerateCallExitNode(const GRState *state); - CFGBlock* getBlock() const { return &B; } const GRState* getState() const { @@ -454,60 +438,6 @@ public: } }; -class GRCallEnterNodeBuilder { - GRCoreEngine &Eng; - - const ExplodedNode *Pred; - - // The call site. - const Stmt *CE; - - // The definition of callee. - const FunctionDecl *FD; - - // The parent block of the CallExpr. - const CFGBlock *Block; - - // The CFGBlock index of the CallExpr. - unsigned Index; - -public: - GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred, - const Stmt *s, const FunctionDecl *fd, - const CFGBlock *blk, unsigned idx) - : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {} - - const GRState *getState() const { return Pred->getState(); } - - const LocationContext *getLocationContext() const { - return Pred->getLocationContext(); - } - - const Stmt *getCallExpr() const { return CE; } - - const FunctionDecl *getCallee() const { return FD; } - - const CFGBlock *getBlock() const { return Block; } - - unsigned getIndex() const { return Index; } - - void GenerateNode(const GRState *state, const LocationContext *LocCtx); -}; - -class GRCallExitNodeBuilder { - GRCoreEngine &Eng; - const ExplodedNode *Pred; - -public: - GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred) - : Eng(eng), Pred(pred) {} - - const ExplodedNode *getPredecessor() const { return Pred; } - - const GRState *getState() const { return Pred->getState(); } - - void GenerateNode(const GRState *state); -}; } // end clang namespace #endif diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 763bbcc9e1..90a2cd5597 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -171,13 +171,7 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. void ProcessEndPath(GREndPathNodeBuilder& builder); - - // Generate the entry node of the callee. - void ProcessCallEnter(GRCallEnterNodeBuilder &builder); - - // Generate the first post callsite node. - void ProcessCallExit(GRCallExitNodeBuilder &builder); - + /// EvalAssume - Callback function invoked by the ConstraintManager when /// making assumptions about state values. const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption); diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index f2cd0486e3..ce57c2c68b 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -28,8 +28,6 @@ class GRBranchNodeBuilder; class GRIndirectGotoNodeBuilder; class GRSwitchNodeBuilder; class GREndPathNodeBuilder; -class GRCallEnterNodeBuilder; -class GRCallExitNodeBuilder; class LocationContext; class GRSubEngine { @@ -66,12 +64,6 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0; - - // Generate the entry node of the callee. - virtual void ProcessCallEnter(GRCallEnterNodeBuilder &builder) = 0; - - // Generate the first post callsite node. - virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0; /// EvalAssume - Called by ConstraintManager. Used to call checker-specific /// logic for handling assumptions on symbolic values. diff --git a/lib/Checker/CallInliner.cpp b/lib/Checker/CallInliner.cpp index 659d9b8bcf..0279d46f22 100644 --- a/lib/Checker/CallInliner.cpp +++ b/lib/Checker/CallInliner.cpp @@ -26,6 +26,7 @@ public: } virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE); + virtual void EvalEndPath(GREndPathNodeBuilder &B,void *tag,GRExprEngine &Eng); }; } @@ -45,10 +46,79 @@ bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) { if (!FD->isThisDeclarationADefinition()) return false; - // Now we have the definition of the callee, create a CallEnter node. - CallEnter Loc(CE, FD, C.getPredecessor()->getLocationContext()); - C.addTransition(state, Loc); + GRStmtNodeBuilder &Builder = C.getNodeBuilder(); + // Make a new LocationContext. + const StackFrameContext *LocCtx = C.getAnalysisManager().getStackFrame(FD, + C.getPredecessor()->getLocationContext(), CE, + Builder.getBlock(), Builder.getIndex()); + + CFGBlock const *Entry = &(LocCtx->getCFG()->getEntry()); + + assert (Entry->empty() && "Entry block must be empty."); + + assert (Entry->succ_size() == 1 && "Entry block must have 1 successor."); + + // Get the solitary successor. + CFGBlock const *SuccB = *(Entry->succ_begin()); + + // Construct an edge representing the starting location in the function. + BlockEdge Loc(Entry, SuccB, LocCtx); + + state = C.getStoreManager().EnterStackFrame(state, LocCtx); + + // This is a hack. We really should not use the GRStmtNodeBuilder. + bool isNew; + GRExprEngine &Eng = C.getEngine(); + ExplodedNode *Pred = C.getPredecessor(); + + + ExplodedNode *SuccN = Eng.getGraph().getNode(Loc, state, &isNew); + SuccN->addPredecessor(Pred, Eng.getGraph()); + C.getNodeBuilder().Deferred.erase(Pred); + + if (isNew) + Builder.getWorkList()->Enqueue(SuccN); + + Builder.HasGeneratedNode = true; return true; } +void CallInliner::EvalEndPath(GREndPathNodeBuilder &B, void *tag, + GRExprEngine &Eng) { + const GRState *state = B.getState(); + + ExplodedNode *Pred = B.getPredecessor(); + + const StackFrameContext *LocCtx = + cast<StackFrameContext>(Pred->getLocationContext()); + // Check if this is the top level stack frame. + if (!LocCtx->getParent()) + return; + + const StackFrameContext *ParentSF = + cast<StackFrameContext>(LocCtx->getParent()); + + SymbolReaper SymReaper(*ParentSF->getLiveVariables(), Eng.getSymbolManager(), + ParentSF); + const Stmt *CE = LocCtx->getCallSite(); + + state = Eng.getStateManager().RemoveDeadBindings(state, const_cast<Stmt*>(CE), + SymReaper); + + + PostStmt NodeLoc(CE, LocCtx->getParent()); + + bool isNew; + ExplodedNode *Succ = Eng.getGraph().getNode(NodeLoc, state, &isNew); + Succ->addPredecessor(Pred, Eng.getGraph()); + + // When creating the new work list unit, increment the statement index to + // point to the statement after the CallExpr. + if (isNew) + B.getWorkList().Enqueue(Succ, + *const_cast<CFGBlock*>(LocCtx->getCallSiteBlock()), + LocCtx->getIndex() + 1); + + B.HasGeneratedNode = true; +} diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp index cc8abc870a..d54b0777ed 100644 --- a/lib/Checker/GRCoreEngine.cpp +++ b/lib/Checker/GRCoreEngine.cpp @@ -144,14 +144,6 @@ void GRCoreEngine::ProcessSwitch(GRSwitchNodeBuilder& Builder) { SubEngine.ProcessSwitch(Builder); } -void GRCoreEngine::ProcessCallEnter(GRCallEnterNodeBuilder &Builder) { - SubEngine.ProcessCallEnter(Builder); -} - -void GRCoreEngine::ProcessCallExit(GRCallExitNodeBuilder &Builder) { - SubEngine.ProcessCallExit(Builder); -} - /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps. bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) { @@ -204,15 +196,6 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) { assert (false && "BlockExit location never occur in forward analysis."); break; - case ProgramPoint::CallEnterKind: - HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(), - WU.getIndex(), Node); - break; - - case ProgramPoint::CallExitKind: - HandleCallExit(cast<CallExit>(Node->getLocation()), Node); - break; - default: assert(isa<PostStmt>(Node->getLocation())); HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(), @@ -224,17 +207,6 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) { return WList->hasWork(); } -void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block, - unsigned Index, ExplodedNode *Pred) { - GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), L.getCallee(), - Block, Index); - ProcessCallEnter(Builder); -} - -void GRCoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) { - GRCallExitNodeBuilder Builder(*this, Pred); - ProcessCallExit(Builder); -} void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) { @@ -428,14 +400,6 @@ GRStmtNodeBuilder::~GRStmtNodeBuilder() { void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) { assert (!N->isSink()); - // Check if this node entered a callee. - if (isa<CallEnter>(N->getLocation())) { - // Still use the index of the CallExpr. It's needed to create the callee - // StackFrameContext. - Eng.WList->Enqueue(N, B, Idx); - return; - } - PostStmt Loc(getStmt(), N->getLocationContext()); if (Loc == N->getLocation()) { @@ -612,13 +576,7 @@ GRSwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) { GREndPathNodeBuilder::~GREndPathNodeBuilder() { // Auto-generate an EOP node if one has not been generated. - if (!HasGeneratedNode) { - // If we are in an inlined call, generate CallExit node. - if (Pred->getLocationContext()->getParent()) - GenerateCallExitNode(Pred->State); - else - generateNode(Pred->State); - } + if (!HasGeneratedNode) generateNode(Pred->State); } ExplodedNode* @@ -639,57 +597,3 @@ GREndPathNodeBuilder::generateNode(const GRState* State, const void *tag, return NULL; } - -void GREndPathNodeBuilder::GenerateCallExitNode(const GRState *state) { - HasGeneratedNode = true; - // Create a CallExit node and enqueue it. - const StackFrameContext *LocCtx - = cast<StackFrameContext>(Pred->getLocationContext()); - const Stmt *CE = LocCtx->getCallSite(); - - // Use the the callee location context. - CallExit Loc(CE, LocCtx); - - bool isNew; - ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew); - Node->addPredecessor(Pred, *Eng.G); - - if (isNew) - Eng.WList->Enqueue(Node); -} - - -void GRCallEnterNodeBuilder::GenerateNode(const GRState *state, - const LocationContext *LocCtx) { - // Get the callee entry block. - const CFGBlock *Entry = &(LocCtx->getCFG()->getEntry()); - assert(Entry->empty()); - assert(Entry->succ_size() == 1); - - // Get the solitary successor. - const CFGBlock *SuccB = *(Entry->succ_begin()); - - // Construct an edge representing the starting location in the callee. - BlockEdge Loc(Entry, SuccB, LocCtx); - - bool isNew; - ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew); - Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G); - - if (isNew) - Eng.WList->Enqueue(Node); -} - -void GRCallExitNodeBuilder::GenerateNode(const GRState *state) { - // Get the callee's location context. - const StackFrameContext *LocCtx - = cast<StackFrameContext>(Pred->getLocationContext()); - - PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent()); - bool isNew; - ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew); - Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G); - if (isNew) - Eng.WList->Enqueue(Node, *const_cast<CFGBlock*>(LocCtx->getCallSiteBlock()), - LocCtx->getIndex() + 1); -} diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 30b82f70ce..7689a35c21 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -1290,38 +1290,6 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) { if (defaultIsFeasible) builder.generateDefaultCaseNode(DefaultSt); } -void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) { - const FunctionDecl *FD = B.getCallee(); - const StackFrameContext *LocCtx = AMgr.getStackFrame(FD, - B.getLocationContext(), - B.getCallExpr(), - B.getBlock(), - B.getIndex()); - - const GRState *state = B.getState(); - state = getStoreManager().EnterStackFrame(state, LocCtx); - - B.GenerateNode(state, LocCtx); -} - -void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) { - const GRState *state = B.getState(); - const ExplodedNode *Pred = B.getPredecessor(); - const StackFrameContext *LocCtx = - cast<StackFrameContext>(Pred->getLocationContext()); - const StackFrameContext *ParentSF = - cast<StackFrameContext>(LocCtx->getParent()); - - SymbolReaper SymReaper(*ParentSF->getLiveVariables(), getSymbolManager(), - ParentSF); - const Stmt *CE = LocCtx->getCallSite(); - - state = getStateManager().RemoveDeadBindings(state, const_cast<Stmt*>(CE), - SymReaper); - - B.GenerateNode(state); -} - //===----------------------------------------------------------------------===// // Transfer functions: logical operations ('&&', '||'). //===----------------------------------------------------------------------===// @@ -3173,14 +3141,6 @@ struct DOTGraphTraits<ExplodedNode*> : assert (false); break; - case ProgramPoint::CallEnterKind: - Out << "CallEnter"; - break; - - case ProgramPoint::CallExitKind: - Out << "CallExit"; - break; - default: { if (StmtPoint *L = dyn_cast<StmtPoint>(&Loc)) { const Stmt* S = L->getStmt(); |