r261293 - [analyzer] Add checker callback for beginning of function.
Devin Coughlin via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 18 17:35:11 PST 2016
Author: dcoughlin
Date: Thu Feb 18 19:35:10 2016
New Revision: 261293
URL: http://llvm.org/viewvc/llvm-project?rev=261293&view=rev
Log:
[analyzer] Add checker callback for beginning of function.
Add a checker callback that is called when the analyzer starts analyzing a
function either at the top level or when inlined. This will be used by a
follow-on patch making the DeallocChecker path sensitive.
Differential Revision: http://reviews.llvm.org/D17418
Added:
cfe/trunk/test/Analysis/traversal-begin-end-function.c
Modified:
cfe/trunk/include/clang/Analysis/ProgramPoint.h
cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
cfe/trunk/test/Analysis/traversal-path-unification.c
Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ProgramPoint.h?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/ProgramPoint.h (original)
+++ cfe/trunk/include/clang/Analysis/ProgramPoint.h Thu Feb 18 19:35:10 2016
@@ -595,6 +595,13 @@ public:
return static_cast<const StackFrameContext *>(getData2());
}
+ /// Returns the entry block in the CFG for the entered function.
+ const CFGBlock *getEntry() const {
+ const StackFrameContext *CalleeCtx = getCalleeContext();
+ const CFG *CalleeCFG = CalleeCtx->getCFG();
+ return &(CalleeCFG->getEntry());
+ }
+
private:
friend class ProgramPoint;
CallEnter() {}
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h Thu Feb 18 19:35:10 2016
@@ -238,6 +238,20 @@ public:
}
};
+class BeginFunction {
+ template <typename CHECKER>
+ static void _checkBeginFunction(void *checker, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkBeginFunction(C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
+ checker, _checkBeginFunction<CHECKER>));
+ }
+};
+
class EndFunction {
template <typename CHECKER>
static void _checkEndFunction(void *checker,
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Thu Feb 18 19:35:10 2016
@@ -287,6 +287,12 @@ public:
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
ExprEngine &Eng);
+ /// \brief Run checkers on begining of function.
+ void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
+ const BlockEdge &L,
+ ExplodedNode *Pred,
+ ExprEngine &Eng);
+
/// \brief Run checkers on end of function.
void runCheckersForEndFunction(NodeBuilderContext &BC,
ExplodedNodeSet &Dst,
@@ -425,7 +431,10 @@ public:
typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
CheckEndAnalysisFunc;
-
+
+ typedef CheckerFn<void (CheckerContext &)>
+ CheckBeginFunctionFunc;
+
typedef CheckerFn<void (CheckerContext &)>
CheckEndFunctionFunc;
@@ -484,6 +493,7 @@ public:
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
+ void _registerForBeginFunction(CheckEndFunctionFunc checkfn);
void _registerForEndFunction(CheckEndFunctionFunc checkfn);
void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
@@ -593,6 +603,7 @@ private:
std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
+ std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h Thu Feb 18 19:35:10 2016
@@ -91,6 +91,9 @@ private:
void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred);
void HandleBlockEntrance(const BlockEntrance &E, ExplodedNode *Pred);
void HandleBlockExit(const CFGBlock *B, ExplodedNode *Pred);
+
+ void HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred);
+
void HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, ExplodedNode *Pred);
void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Thu Feb 18 19:35:10 2016
@@ -253,8 +253,14 @@ public:
/// nodes by processing the 'effects' of a switch statement.
void processSwitch(SwitchNodeBuilder& builder) override;
- /// Called by CoreEngine. Used to generate end-of-path
- /// nodes when the control reaches the end of a function.
+ /// Called by CoreEngine. Used to notify checkers that processing a
+ /// function has begun. Called for both inlined and and top-level functions.
+ void processBeginOfFunction(NodeBuilderContext &BC,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst,
+ const BlockEdge &L) override;
+
+ /// Called by CoreEngine. Used to notify checkers that processing a
+ /// function has ended. Called for both inlined and and top-level functions.
void processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred) override;
@@ -264,7 +270,8 @@ public:
ExplodedNodeSet &Dst);
/// Generate the entry node of the callee.
- void processCallEnter(CallEnter CE, ExplodedNode *Pred) override;
+ void processCallEnter(NodeBuilderContext& BC, CallEnter CE,
+ ExplodedNode *Pred) override;
/// Generate the sequence of nodes that simulate the call exit and the post
/// visit for CallExpr.
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h Thu Feb 18 19:35:10 2016
@@ -99,13 +99,21 @@ public:
/// nodes by processing the 'effects' of a switch statement.
virtual void processSwitch(SwitchNodeBuilder& builder) = 0;
- /// Called by CoreEngine. Used to generate end-of-path
- /// nodes when the control reaches the end of a function.
+ /// Called by CoreEngine. Used to notify checkers that processing a
+ /// function has begun. Called for both inlined and and top-level functions.
+ virtual void processBeginOfFunction(NodeBuilderContext &BC,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const BlockEdge &L) = 0;
+
+ /// Called by CoreEngine. Used to notify checkers that processing a
+ /// function has ended. Called for both inlined and and top-level functions.
virtual void processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred) = 0;
// Generate the entry node of the callee.
- virtual void processCallEnter(CallEnter CE, ExplodedNode *Pred) = 0;
+ virtual void processCallEnter(NodeBuilderContext& BC, CallEnter CE,
+ ExplodedNode *Pred) = 0;
// Generate the first post callsite node.
virtual void processCallExit(ExplodedNode *Pred) = 0;
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp Thu Feb 18 19:35:10 2016
@@ -162,8 +162,16 @@ public:
/// check::DeadSymbols
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const {}
+
+ /// \brief Called when the analyzer core starts analyzing a function,
+ /// regardless of whether it is analyzed at the top level or is inlined.
+ ///
+ /// check::BeginFunction
+ void checkBeginFunction(CheckerContext &Ctx) const {}
+
/// \brief Called when the analyzer core reaches the end of a
- /// function being analyzed.
+ /// function being analyzed regardless of whether it is analyzed at the top
+ /// level or is inlined.
///
/// check::EndFunction
void checkEndFunction(CheckerContext &Ctx) const {}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp Thu Feb 18 19:35:10 2016
@@ -25,9 +25,11 @@ using namespace ento;
namespace {
class TraversalDumper : public Checker< check::BranchCondition,
+ check::BeginFunction,
check::EndFunction > {
public:
void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
+ void checkBeginFunction(CheckerContext &C) const;
void checkEndFunction(CheckerContext &C) const;
};
}
@@ -50,6 +52,10 @@ void TraversalDumper::checkBranchConditi
<< Parent->getStmtClassName() << "\n";
}
+void TraversalDumper::checkBeginFunction(CheckerContext &C) const {
+ llvm::outs() << "--BEGIN FUNCTION--\n";
+}
+
void TraversalDumper::checkEndFunction(CheckerContext &C) const {
llvm::outs() << "--END FUNCTION--\n";
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Thu Feb 18 19:35:10 2016
@@ -377,6 +377,40 @@ void CheckerManager::runCheckersForEndAn
EndAnalysisCheckers[i](G, BR, Eng);
}
+namespace {
+struct CheckBeginFunctionContext {
+ typedef std::vector<CheckerManager::CheckBeginFunctionFunc> CheckersTy;
+ const CheckersTy &Checkers;
+ ExprEngine &Eng;
+ const ProgramPoint &PP;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
+ const ProgramPoint &PP)
+ : Checkers(Checkers), Eng(Eng), PP(PP) {}
+
+ void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
+ NodeBuilder &Bldr, ExplodedNode *Pred) {
+ const ProgramPoint &L = PP.withTag(checkFn.Checker);
+ CheckerContext C(Bldr, Eng, Pred, L);
+
+ checkFn(C);
+ }
+};
+}
+
+void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
+ const BlockEdge &L,
+ ExplodedNode *Pred,
+ ExprEngine &Eng) {
+ ExplodedNodeSet Src;
+ Src.insert(Pred);
+ CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
/// \brief Run checkers for end of path.
// Note, We do not chain the checker output (like in expandGraphWithCheckers)
// for this callback since end of path nodes are expected to be final.
@@ -671,6 +705,10 @@ void CheckerManager::_registerForEndAnal
EndAnalysisCheckers.push_back(checkfn);
}
+void CheckerManager::_registerForBeginFunction(CheckBeginFunctionFunc checkfn) {
+ BeginFunctionCheckers.push_back(checkfn);
+}
+
void CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
EndFunctionCheckers.push_back(checkfn);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Thu Feb 18 19:35:10 2016
@@ -192,10 +192,18 @@ bool CoreEngine::ExecuteWorkList(const L
WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
if (!InitState)
- // Generate the root.
- generateNode(StartLoc, SubEng.getInitialState(L), nullptr);
- else
- generateNode(StartLoc, InitState, nullptr);
+ InitState = SubEng.getInitialState(L);
+
+ bool IsNew;
+ ExplodedNode *Node = G.getNode(StartLoc, InitState, false, &IsNew);
+ assert (IsNew);
+ G.addRoot(Node);
+
+ NodeBuilderContext BuilderCtx(*this, StartLoc.getDst(), Node);
+ ExplodedNodeSet DstBegin;
+ SubEng.processBeginOfFunction(BuilderCtx, Node, DstBegin, StartLoc);
+
+ enqueue(DstBegin);
}
// Check if we have a steps limit
@@ -243,8 +251,7 @@ void CoreEngine::dispatchWorkItem(Explod
break;
case ProgramPoint::CallEnterKind: {
- CallEnter CEnter = Loc.castAs<CallEnter>();
- SubEng.processCallEnter(CEnter, Pred);
+ HandleCallEnter(Loc.castAs<CallEnter>(), Pred);
break;
}
@@ -456,6 +463,11 @@ void CoreEngine::HandleBlockExit(const C
Pred->State, Pred);
}
+void CoreEngine::HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred) {
+ NodeBuilderContext BuilderCtx(*this, CE.getEntry(), Pred);
+ SubEng.processCallEnter(BuilderCtx, CE, Pred);
+}
+
void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
const CFGBlock * B, ExplodedNode *Pred) {
assert(B->succ_size() == 2);
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Thu Feb 18 19:35:10 2016
@@ -30,6 +30,7 @@
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SaveAndRestore.h"
#ifndef NDEBUG
#include "llvm/Support/GraphWriter.h"
@@ -1749,6 +1750,14 @@ static bool stackFrameDoesNotContainInit
}
#endif
+void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const BlockEdge &L) {
+ SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
+ getCheckerManager().runCheckersForBeginFunction(Dst, L, Pred, *this);
+}
+
/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Thu Feb 18 19:35:10 2016
@@ -37,13 +37,12 @@ STATISTIC(NumInlinedCalls,
STATISTIC(NumReachedInlineCountMax,
"The # of times we reached inline count maximum");
-void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
+void ExprEngine::processCallEnter(NodeBuilderContext& BC, CallEnter CE,
+ ExplodedNode *Pred) {
// Get the entry block in the CFG of the callee.
const StackFrameContext *calleeCtx = CE.getCalleeContext();
PrettyStackTraceLocationContext CrashInfo(calleeCtx);
-
- const CFG *CalleeCFG = calleeCtx->getCFG();
- const CFGBlock *Entry = &(CalleeCFG->getEntry());
+ const CFGBlock *Entry = CE.getEntry();
// Validate the CFG.
assert(Entry->empty());
@@ -57,12 +56,16 @@ void ExprEngine::processCallEnter(CallEn
ProgramStateRef state = Pred->getState();
- // Construct a new node and add it to the worklist.
+ // Construct a new node, notify checkers that analysis of the function has
+ // begun, and add the resultant nodes to the worklist.
bool isNew;
ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);
Node->addPredecessor(Pred, G);
- if (isNew)
- Engine.getWorkList()->enqueue(Node);
+ if (isNew) {
+ ExplodedNodeSet DstBegin;
+ processBeginOfFunction(BC, Node, DstBegin, Loc);
+ Engine.enqueue(DstBegin);
+ }
}
// Find the last statement on the path to the exploded node and the
Added: cfe/trunk/test/Analysis/traversal-begin-end-function.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/traversal-begin-end-function.c?rev=261293&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/traversal-begin-end-function.c (added)
+++ cfe/trunk/test/Analysis/traversal-begin-end-function.c Thu Feb 18 19:35:10 2016
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.DumpTraversal %s | FileCheck %s
+
+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)
+ return;
+
+ inline_callee(i - 1);
+}
Modified: cfe/trunk/test/Analysis/traversal-path-unification.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/traversal-path-unification.c?rev=261293&r1=261292&r2=261293&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/traversal-path-unification.c (original)
+++ cfe/trunk/test/Analysis/traversal-path-unification.c Thu Feb 18 19:35:10 2016
@@ -11,6 +11,7 @@ int c();
#define CHECK(x) (x)
#endif
+// CHECK: --BEGIN FUNCTION--
void testRemoveDeadBindings() {
int i = a();
if (CHECK(i))
More information about the cfe-commits
mailing list