]> granicus.if.org Git - clang/commitdiff
Add 'VisitEndAnalysis' callback to Checker class. This callback is called by GRExprE...
authorTed Kremenek <kremenek@apple.com>
Wed, 23 Jun 2010 22:08:00 +0000 (22:08 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 23 Jun 2010 22:08:00 +0000 (22:08 +0000)
when the worklist algorithm has terminated.  This allows some checkers to do a post-analysis
phase after all paths have been analyzed.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106689 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Checker/PathSensitive/Checker.h
include/clang/Checker/PathSensitive/GRExprEngine.h
include/clang/Checker/PathSensitive/GRSubEngine.h
lib/Checker/GRCoreEngine.cpp
lib/Checker/GRExprEngine.cpp

index dcb4ca62b83c58f8f4ac14e312f53b711cbc6d8d..034c30535919994cdb6212676f0e826f3a70a08d 100644 (file)
@@ -279,6 +279,9 @@ public:
                                     bool Assumption) {
     return state;
   }
+
+  virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
+                                bool hasWorkRemaining) {}
 };
 } // end clang namespace
 
index ac407f6933c860e0f8ebd45d57d5d0cba7853b77..cb5c0a70fc98b881af5311294bd462cc914dcbf2 100644 (file)
@@ -178,12 +178,15 @@ public:
   ///  nodes when the control reaches the end of a function.
   void ProcessEndPath(GREndPathNodeBuilder& builder);
 
-  // Generate the entry node of the callee.
+  /// Generate the entry node of the callee.
   void ProcessCallEnter(GRCallEnterNodeBuilder &builder);
 
-  // Generate the first post callsite node.
+  /// Generate the first post callsite node.
   void ProcessCallExit(GRCallExitNodeBuilder &builder);
 
+  /// Called by GRCoreEngine when the analysis worklist has terminated.
+  void ProcessEndWorklist(bool hasWorkRemaining);
+
   /// EvalAssume - Callback function invoked by the ConstraintManager when
   ///  making assumptions about state values.
   const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption);
index d2e7457ea93d7664d9e9389215411abbed16e45a..90a41d7c093f8150d4f7d9a2eb3aa5244ecb8a2c 100644 (file)
@@ -41,27 +41,27 @@ public:
 
   virtual GRStateManager& getStateManager() = 0;
 
-  /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
-  ///  nodes by processing the 'effects' of a block-level statement.
+  /// Called by GRCoreEngine. Used to generate new successor
+  /// nodes by processing the 'effects' of a block-level statement.
   virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0;
 
-  /// ProcessBlockEntrance - Called by GRCoreEngine when start processing
-  ///  a CFGBlock.  This method returns true if the analysis should continue
-  ///  exploring the given path, and false otherwise.
+  /// Called by GRCoreEngine when start processing
+  /// a CFGBlock.  This method returns true if the analysis should continue
+  /// exploring the given path, and false otherwise.
   virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
                                     GRBlockCounter BC) = 0;
 
-  /// ProcessBranch - Called by GRCoreEngine.  Used to generate successor
+  /// Called by GRCoreEngine.  Used to generate successor
   ///  nodes by processing the 'effects' of a branch condition.
   virtual void ProcessBranch(Stmt* Condition, Stmt* Term,
                              GRBranchNodeBuilder& builder) = 0;
 
-  /// ProcessIndirectGoto - Called by GRCoreEngine.  Used to generate successor
-  ///  nodes by processing the 'effects' of a computed goto jump.
+  /// Called by GRCoreEngine.  Used to generate successor
+  /// nodes by processing the 'effects' of a computed goto jump.
   virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) = 0;
 
-  /// ProcessSwitch - Called by GRCoreEngine.  Used to generate successor
-  ///  nodes by processing the 'effects' of a switch statement.
+  /// Called by GRCoreEngine.  Used to generate successor
+  /// nodes by processing the 'effects' of a switch statement.
   virtual void ProcessSwitch(GRSwitchNodeBuilder& builder) = 0;
 
   /// ProcessEndPath - Called by GRCoreEngine.  Used to generate end-of-path
@@ -74,10 +74,14 @@ public:
   // 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.
+  /// Called by ConstraintManager. Used to call checker-specific
+  /// logic for handling assumptions on symbolic values.
   virtual const GRState* ProcessAssume(const GRState *state,
                                        SVal cond, bool assumption) = 0;
+  
+  /// Called by GRCoreEngine when the analysis worklist is either empty or the
+  //  maximum number of analysis steps have been reached.
+  virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0;
 };
 }
 
index 23a87d303b4d447915fe9c9db2b289356a436108..36f330303c372758cd1c3243cd0e3cfeade84e12 100644 (file)
@@ -221,6 +221,7 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
     }
   }
 
+  SubEngine.ProcessEndWorklist(WList->hasWork());
   return WList->hasWork();
 }
 
index d84301f0b9ee4537b1badc5f3c62d969f5e2eee8..b7b3502ccce379f8f0a03906b05b2f0ea4c19687 100644 (file)
@@ -466,6 +466,13 @@ const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
   return TF->EvalAssume(state, cond, assumption);
 }
 
+void GRExprEngine::ProcessEndWorklist(bool hasWorkRemaining) {
+  for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+       I != E; ++I) {
+    I->second->VisitEndAnalysis(G, BR, hasWorkRemaining);
+  }
+}
+
 void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
   CurrentStmt = CE.getStmt();
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),