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)) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits