From f380534a1abb84f829846b7eda21318fa4666df3 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Tue, 25 Oct 2011 19:56:54 +0000 Subject: [PATCH] [analyzer] Make branch for condition callback use CheckerContext Now, all the path sensitive checkers use CheckerContext! llvm-svn: 142944 --- .../clang/StaticAnalyzer/Core/Checker.h | 7 ++-- .../StaticAnalyzer/Core/CheckerManager.h | 5 ++- .../Checkers/UndefBranchChecker.cpp | 19 +++------- .../StaticAnalyzer/Core/CheckerManager.cpp | 36 +++++++++++++++---- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 21 ++++++----- 5 files changed, 53 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/Checker.h b/clang/include/clang/StaticAnalyzer/Core/Checker.h index 181080a21345..358510ef0b08 100644 --- a/clang/include/clang/StaticAnalyzer/Core/Checker.h +++ b/clang/include/clang/StaticAnalyzer/Core/Checker.h @@ -214,10 +214,9 @@ public: class BranchCondition { template - static void _checkBranchCondition(void *checker, const Stmt *condition, - NodeBuilder &B, ExplodedNode *Pred, - ExprEngine &Eng) { - ((const CHECKER *)checker)->checkBranchCondition(condition, B, Pred, Eng); + static void _checkBranchCondition(void *checker, const Stmt *Condition, + CheckerContext & C) { + ((const CHECKER *)checker)->checkBranchCondition(Condition, C); } public: diff --git a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index e74bd8b826ad..806085460bae 100644 --- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -236,7 +236,7 @@ public: /// \brief Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, - NodeBuilder &B, ExplodedNode *Pred, + ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng); /// \brief Run checkers for live symbols. @@ -339,8 +339,7 @@ public: typedef CheckerFn CheckEndPathFunc; - typedef CheckerFn + typedef CheckerFn CheckBranchConditionFunc; typedef CheckerFn diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp index d030469459fe..afb79b5d166f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -49,27 +49,18 @@ class UndefBranchChecker : public Checker { }; public: - void checkBranchCondition(const Stmt *Condition, NodeBuilder &Builder, - ExplodedNode *Pred, ExprEngine &Eng) const; + void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const; }; } void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, - NodeBuilder &Builder, - ExplodedNode *Pred, - ExprEngine &Eng) const { - const ProgramState *state = Pred->getState(); - SVal X = state->getSVal(Condition); + CheckerContext &Ctx) const { + SVal X = Ctx.getState()->getSVal(Condition); if (X.isUndef()) { - // TODO: The PP will be generated with the correct tag by the CheckerManager - // after we migrate the callback to CheckerContext. - const ProgramPointTag *Tag = 0; - ProgramPoint PP = PostCondition(Condition, Pred->getLocationContext(), Tag); // Generate a sink node, which implicitly marks both outgoing branches as // infeasible. - ExplodedNode *N = Builder.generateNode(PP, state, - Pred, true); + ExplodedNode *N = Ctx.generateSink(); if (N) { if (!BT) BT.reset( @@ -107,7 +98,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex)); R->addRange(Ex->getSourceRange()); - Eng.getBugReporter().EmitReport(R); + Ctx.EmitReport(R); } } } diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp index 67fe4d6ca219..ecb1a7a4ce3a 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -320,15 +320,39 @@ void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC, } } +namespace { + struct CheckBranchConditionContext { + typedef std::vector CheckersTy; + const CheckersTy &Checkers; + const Stmt *Condition; + ExprEngine &Eng; + + CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } + CheckersTy::const_iterator checkers_end() { return Checkers.end(); } + + CheckBranchConditionContext(const CheckersTy &checkers, + const Stmt *Cond, ExprEngine &eng) + : Checkers(checkers), Condition(Cond), Eng(eng) {} + + void runChecker(CheckerManager::CheckBranchConditionFunc checkFn, + NodeBuilder &Bldr, ExplodedNode *Pred) { + ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(), + checkFn.Checker); + CheckerContext C(Bldr, Eng, Pred, L, 0); + checkFn(Condition, C); + } + }; +} + /// \brief Run checkers for branch condition. -void CheckerManager::runCheckersForBranchCondition(const Stmt *condition, - NodeBuilder &B, +void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition, + ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng) { - for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { - CheckBranchConditionFunc fn = BranchConditionCheckers[i]; - fn(condition, B, Pred, Eng); - } + ExplodedNodeSet Src; + Src.insert(Pred); + CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng); + expandGraphWithCheckers(C, Dst, Src); } /// \brief Run checkers for live symbols. diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 3e5a31cda001..8ba2cd80a22e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -217,10 +217,13 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred, ProcessImplicitDtor(*E.getAs(), Pred); return; } + currentStmtIdx = 0; + currentBuilderContext = 0; } const Stmt *ExprEngine::getStmt() const { - const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx].getAs(); + const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx] + .getAs(); return CS ? CS->getStmt() : 0; } @@ -1033,6 +1036,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) { + currentBuilderContext = &BldCtx; + // Check for NULL conditions; e.g. "for(;;)" if (!Condition) { BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF); @@ -1045,17 +1050,16 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, Condition->getLocStart(), "Error evaluating branch"); - ExplodedNodeSet TmpCheckersOut; - NodeBuilder CheckerBldr(Pred, TmpCheckersOut, BldCtx); - getCheckerManager().runCheckersForBranchCondition(Condition, CheckerBldr, + ExplodedNodeSet CheckersOutSet; + getCheckerManager().runCheckersForBranchCondition(Condition, CheckersOutSet, Pred, *this); // We generated only sinks. - if (TmpCheckersOut.empty()) + if (CheckersOutSet.empty()) return; - BranchNodeBuilder builder(CheckerBldr.getResults(), Dst, BldCtx, DstT, DstF); - for (NodeBuilder::iterator I = CheckerBldr.begin(), - E = CheckerBldr.end(); E != I; ++I) { + BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF); + for (NodeBuilder::iterator I = CheckersOutSet.begin(), + E = CheckersOutSet.end(); E != I; ++I) { ExplodedNode *PredI = *I; if (PredI->isSink()) @@ -1107,6 +1111,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, builder.markInfeasible(false); } } + currentBuilderContext = 0; } /// processIndirectGoto - Called by CoreEngine. Used to generate successor