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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits