Charusso created this revision.
Charusso added a reviewer: NoQ.
Charusso added a project: clang.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.
Charusso added a parent revision: D69731: [analyzer] CheckerContext: Make the 
Preprocessor available.

This callback is called when the analysis starts. It could be used to
construct the fields of the checker. Here is an example:

  void CoolFuncChecker::checkBeginAnalysis(CheckerContext &C) const {
    CheckerManager &Mgr = C.getCheckerManager();
  
    CheckCoolFunctions = Mgr.getAnalyzerOptions().getCheckerBooleanOption(
        this, "WantToCheckCoolFunctions");
  
    BT = std::make_unique<BugType>(Mgr.getCurrentCheckerName(),
                                   "Cool function call", categories::TooCool);
  
    Preprocessor &PP = C.getPreprocessor();
    UseMyCoolLib = PP.isMacroDefined("__MY_COOL_LIB__");
  }


Repository:
  rC Clang

https://reviews.llvm.org/D69745

Files:
  clang/include/clang/StaticAnalyzer/Core/Checker.h
  clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
  clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
  clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/test/Analysis/traversal-begin-end-function.c

Index: clang/test/Analysis/traversal-begin-end-function.c
===================================================================
--- clang/test/Analysis/traversal-begin-end-function.c
+++ clang/test/Analysis/traversal-begin-end-function.c
@@ -2,17 +2,9 @@
 
 void inline_callee(int i);
 
-// CHECK: --BEGIN FUNCTION--
 void inline_caller() {
-  // CHECK: --BEGIN FUNCTION--
-  // CHECK: --BEGIN FUNCTION--
-  // CHECK: --BEGIN FUNCTION--
   inline_callee(3);
-  // CHECK: --END FUNCTION--
-  // CHECK: --END FUNCTION--
-  // CHECK: --END FUNCTION--
 }
-// CHECK: --END FUNCTION--
 
 void inline_callee(int i) {
   if (i <= 1)
@@ -20,3 +12,17 @@
 
   inline_callee(i - 1);
 }
+
+// CHECK:      --BEGIN ANALYSIS--
+// CHECK-NEXT: --BEGIN FUNCTION--
+// CHECK-NEXT: --BEGIN FUNCTION--
+// CHECK-NEXT: IfStmt
+// CHECK-NEXT: --BEGIN FUNCTION--
+// CHECK-NEXT: IfStmt
+// CHECK-NEXT: --BEGIN FUNCTION--
+// CHECK-NEXT: IfStmt
+// CHECK-NEXT: --END FUNCTION--
+// CHECK-NEXT: --END FUNCTION--
+// CHECK-NEXT: --END FUNCTION--
+// CHECK-NEXT: --END FUNCTION--
+// CHECK-NEXT: --END ANALYSIS--
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -620,6 +620,13 @@
                                                    IsDot);
 }
 
+void ExprEngine::processBeginWorklist(NodeBuilderContext &NBC,
+                                      ExplodedNode *Pred, ExplodedNodeSet &Dst,
+                                      const BlockEdge &L) {
+  SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &NBC);
+  getCheckerManager().runCheckersForBeginAnalysis(Dst, L, Pred, *this);
+}
+
 void ExprEngine::processEndWorklist() {
   getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
 }
Index: clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -113,6 +113,8 @@
 
     NodeBuilderContext BuilderCtx(*this, StartLoc.getDst(), Node);
     ExplodedNodeSet DstBegin;
+
+    SubEng.processBeginWorklist(BuilderCtx, Node, DstBegin, StartLoc);
     SubEng.processBeginOfFunction(BuilderCtx, Node, DstBegin, StartLoc);
 
     enqueue(DstBegin);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -399,6 +399,41 @@
   expandGraphWithCheckers(C, Dst, Src);
 }
 
+namespace {
+struct CheckBeginAnalysisContext {
+  using CheckersTy = std::vector<CheckerManager::CheckBeginAnalysisFunc>;
+
+  const CheckersTy &Checkers;
+  ExprEngine &Eng;
+  const ProgramPoint &PP;
+
+  CheckBeginAnalysisContext(const CheckersTy &Checkers, ExprEngine &Eng,
+                            const ProgramPoint &PP)
+      : Checkers(Checkers), Eng(Eng), PP(PP) {}
+
+  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+  void runChecker(CheckerManager::CheckBeginAnalysisFunc checkFn,
+                  NodeBuilder &Bldr, ExplodedNode *Pred) {
+    const ProgramPoint &L = PP.withTag(checkFn.Checker);
+    CheckerContext C(Bldr, Eng, Pred, L);
+
+    checkFn(C);
+  }
+};
+} // namespace
+
+void CheckerManager::runCheckersForBeginAnalysis(ExplodedNodeSet &Dst,
+                                                 const BlockEdge &L,
+                                                 ExplodedNode *Pred,
+                                                 ExprEngine &Eng) {
+  ExplodedNodeSet Src;
+  Src.insert(Pred);
+  CheckBeginAnalysisContext C(BeginAnalysisCheckers, Eng, L);
+  expandGraphWithCheckers(C, Dst, Src);
+}
+
 void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
                                                BugReporter &BR,
                                                ExprEngine &Eng) {
@@ -827,6 +862,10 @@
   BindCheckers.push_back(checkfn);
 }
 
+void CheckerManager::_registerForBeginAnalysis(CheckBeginAnalysisFunc checkfn) {
+  BeginAnalysisCheckers.push_back(checkfn);
+}
+
 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
   EndAnalysisCheckers.push_back(checkfn);
 }
Index: clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
@@ -23,10 +23,14 @@
 using namespace ento;
 
 namespace {
-class TraversalDumper : public Checker< check::BranchCondition,
-                                        check::BeginFunction,
-                                        check::EndFunction > {
+class TraversalDumper
+    : public Checker<check::BeginAnalysis, check::EndAnalysis,
+                     check::BranchCondition, check::BeginFunction,
+                     check::EndFunction> {
 public:
+  void checkBeginAnalysis(CheckerContext &C) const;
+  void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+                        ExprEngine &Eng) const;
   void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
   void checkBeginFunction(CheckerContext &C) const;
   void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
@@ -51,6 +55,15 @@
                << Parent->getStmtClassName() << "\n";
 }
 
+void TraversalDumper::checkBeginAnalysis(CheckerContext &) const {
+  llvm::outs() << "--BEGIN ANALYSIS--\n";
+}
+
+void TraversalDumper::checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+                                       ExprEngine &Eng) const {
+  llvm::outs() << "--END ANALYSIS--\n";
+}
+
 void TraversalDumper::checkBeginFunction(CheckerContext &C) const {
   llvm::outs() << "--BEGIN FUNCTION--\n";
 }
Index: clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -47,6 +47,7 @@
                                        check::DeadSymbols,
                                        check::BeginFunction,
                                        check::EndFunction,
+                                       check::BeginAnalysis,
                                        check::EndAnalysis,
                                        check::EndOfTranslationUnit,
                                        eval::Call,
@@ -193,6 +194,13 @@
   /// check::EndFunction
   void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const {}
 
+  /// Called when the analysis starts.
+  ///
+  /// This callback should be used to construct the checker's fields.
+  ///
+  /// check::BeginAnalysis
+  void checkBeginAnalysis(const Decl *D, BugReporter &BR);
+
   /// Called after all the paths in the ExplodedGraph reach end of path
   /// - the symbolic execution graph is fully explored.
   ///
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -163,8 +163,13 @@
                          const LocationContext *LCtx, const char *NL,
                          unsigned int Space, bool IsDot) const = 0;
 
+  /// Called by CoreEngine when the analysis worklist starts.
+  virtual void processBeginWorklist(NodeBuilderContext &NBC, ExplodedNode *Pred,
+                                    ExplodedNodeSet &Dst,
+                                    const BlockEdge &L) = 0;
+
   /// Called by CoreEngine when the analysis worklist is either empty or the
-  //  maximum number of analysis steps have been reached.
+  /// maximum number of analysis steps have been reached.
   virtual void processEndWorklist() = 0;
 };
 
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -358,6 +358,10 @@
   /// visit for CallExpr.
   void processCallExit(ExplodedNode *Pred) override;
 
+  /// Called by CoreEngine when the analysis worklist starts.
+  void processBeginWorklist(NodeBuilderContext &NBC, ExplodedNode *Pred,
+                            ExplodedNodeSet &Dst, const BlockEdge &L) override;
+
   /// Called by CoreEngine when the analysis worklist has terminated.
   void processEndWorklist() override;
 
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -56,6 +56,8 @@
     return Eng.getAnalysisManager();
   }
 
+  CheckerManager &getCheckerManager() { return Eng.getCheckerManager(); }
+
   ConstraintManager &getConstraintManager() {
     return Eng.getConstraintManager();
   }
Index: clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -299,6 +299,10 @@
                           const Stmt *S, ExprEngine &Eng,
                           const ProgramPoint &PP);
 
+  /// Run checkers for begin of analysis.
+  void runCheckersForBeginAnalysis(ExplodedNodeSet &Dst, const BlockEdge &L,
+                                   ExplodedNode *Pred, ExprEngine &Eng);
+
   /// Run checkers for end of analysis.
   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
                                  ExprEngine &Eng);
@@ -455,6 +459,8 @@
       CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S,
                       CheckerContext &)>;
 
+  using CheckBeginAnalysisFunc = CheckerFn<void(CheckerContext &)>;
+
   using CheckEndAnalysisFunc =
       CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
 
@@ -517,6 +523,7 @@
 
   void _registerForBind(CheckBindFunc checkfn);
 
+  void _registerForBeginAnalysis(CheckBeginAnalysisFunc checkfn);
   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
 
   void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
@@ -628,6 +635,7 @@
 
   std::vector<CheckBindFunc> BindCheckers;
 
+  std::vector<CheckBeginAnalysisFunc> BeginAnalysisCheckers;
   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
 
   std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
Index: clang/include/clang/StaticAnalyzer/Core/Checker.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/Checker.h
+++ clang/include/clang/StaticAnalyzer/Core/Checker.h
@@ -223,6 +223,20 @@
   }
 };
 
+class BeginAnalysis {
+  template <typename CHECKER>
+  static void _checkBeginAnalysis(void *checker, CheckerContext &C) {
+    ((const CHECKER *)checker)->checkBeginAnalysis(C);
+  }
+
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerForBeginAnalysis(CheckerManager::CheckBeginAnalysisFunc(
+        checker, _checkBeginAnalysis<CHECKER>));
+  }
+};
+
 class EndAnalysis {
   template <typename CHECKER>
   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to