diff options
-rw-r--r-- | include/clang/StaticAnalyzer/Core/Checker.h | 2 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/CheckerManager.h | 6 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h | 2 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h | 35 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp | 18 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 15 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 89 |
8 files changed, 86 insertions, 83 deletions
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 1e4edeb0c7..51533489e5 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -215,7 +215,7 @@ public: class BranchCondition { template <typename CHECKER> static void _checkBranchCondition(void *checker, const Stmt *condition, - BranchNodeBuilder &B, ExprEngine &Eng) { + NodeBuilder &B, ExprEngine &Eng) { ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng); } diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index e3e4c49f71..6026aec643 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -39,7 +39,7 @@ namespace ento { class ExplodedGraph; class ProgramState; class EndOfFunctionNodeBuilder; - class BranchNodeBuilder; + class NodeBuilder; class MemRegion; class SymbolReaper; @@ -232,7 +232,7 @@ public: /// \brief Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, - BranchNodeBuilder &B, ExprEngine &Eng); + NodeBuilder &B, ExprEngine &Eng); /// \brief Run checkers for live symbols. /// @@ -334,7 +334,7 @@ public: typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)> CheckEndPathFunc; - typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)> + typedef CheckerFn<void (const Stmt *, NodeBuilder &, ExprEngine &)> CheckBranchConditionFunc; typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index e366b065c0..1bbc66ced7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -51,7 +51,7 @@ public: ST(st), size(Dst.size()), Ctx(builder.Eng, builder.getBlock()), - NB(Ctx, pred), + NB(pred, Ctx), respondsToCallback(respondsToCB) { assert(!(ST && ST != Pred->getState())); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 7629ac4a67..ac174c4b39 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -181,7 +181,7 @@ protected: friend class StmtNodeBuilder; ExplodedNode *BuilderPred; - NodeBuilderContext &C; + const NodeBuilderContext &C; bool Finalized; /// \brief The frontier set - a set of nodes which need to be propagated after @@ -212,12 +212,19 @@ protected: bool MarkAsSink = false); public: - NodeBuilder(NodeBuilderContext &Ctx, ExplodedNode *N) + NodeBuilder(ExplodedNode *N, NodeBuilderContext &Ctx) : BuilderPred(N), C(Ctx), Finalized(false) { assert(!N->isSink()); Deferred.insert(N); } + /// Create a new builder using the parent builder's context. + NodeBuilder(ExplodedNode *N, const NodeBuilder &ParentBldr) + : BuilderPred(N), C(ParentBldr.C), Finalized(false) { + assert(!N->isSink()); + Deferred.insert(N); + } + virtual ~NodeBuilder() {} /// \brief Generates a node in the ExplodedGraph. @@ -258,7 +265,11 @@ public: C.Block->getBlockID()); } + // \brief Get the builder's predecessor - the parent to all the other nodes. ExplodedNode *getPredecessor() const { return BuilderPred; } + + // \brief Returns state of the predecessor. + const ProgramState *getState() const { return BuilderPred->getState(); } }; class CommonNodeBuilder { @@ -409,19 +420,19 @@ class BranchNodeBuilder: public NodeBuilder { } public: - BranchNodeBuilder(NodeBuilderContext &C, ExplodedNode *Pred, + BranchNodeBuilder(ExplodedNode *Pred, NodeBuilderContext &C, const CFGBlock *dstT, const CFGBlock *dstF) - : NodeBuilder(C, Pred), DstT(dstT), DstF(dstF), + : NodeBuilder(Pred, C), DstT(dstT), DstF(dstF), GeneratedTrue(false), GeneratedFalse(false), InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { } - /// This function generate a new ExplodedNode but not a new - /// branch(block edge). Creates a transition from the Builder's top - /// predecessor. - ExplodedNode *generateNode(const Stmt *Condition, const ProgramState *State, - const ProgramPointTag *Tag = 0, - bool MarkAsSink = false); + /// Create a new builder using the parent builder's context. + BranchNodeBuilder(ExplodedNode *Pred, BranchNodeBuilder &ParentBldr) + : NodeBuilder(Pred, ParentBldr), DstT(ParentBldr.DstT), DstF(ParentBldr.DstF), + GeneratedTrue(false), GeneratedFalse(false), + InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { + } ExplodedNode *generateNode(const ProgramState *State, bool branch, ExplodedNode *Pred = 0); @@ -440,10 +451,6 @@ public: bool isFeasible(bool branch) { return branch ? !InFeasibleTrue : !InFeasibleFalse; } - - const ProgramState *getState() const { - return getPredecessor()->getState(); - } }; class IndirectGotoNodeBuilder { diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp index 8663893f2e..451fa91b3a 100644 --- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -49,20 +49,27 @@ class UndefBranchChecker : public Checker<check::BranchCondition> { }; public: - void checkBranchCondition(const Stmt *Condition, BranchNodeBuilder &Builder, + void checkBranchCondition(const Stmt *Condition, NodeBuilder &Builder, ExprEngine &Eng) const; }; } void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, - BranchNodeBuilder &Builder, + NodeBuilder &Builder, ExprEngine &Eng) const { const ProgramState *state = Builder.getState(); SVal X = state->getSVal(Condition); if (X.isUndef()) { - // Generate a sink node. - ExplodedNode *N = Builder.generateNode(Condition, state, 0, true); + // 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, + Builder.getPredecessor()->getLocationContext(), Tag); + // Generate a sink node, which implicitly marks both outgoing branches as + // infeasible. + ExplodedNode *N = Builder.generateNode(PP, state, + Builder.getPredecessor(), true); if (N) { if (!BT) BT.reset( @@ -102,9 +109,6 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, Eng.getBugReporter().EmitReport(R); } - - Builder.markInfeasible(true); - Builder.markInfeasible(false); } } diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index acacfb0e18..d47033a70e 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -297,7 +297,7 @@ void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, /// \brief Run checkers for branch condition. void CheckerManager::runCheckersForBranchCondition(const Stmt *condition, - BranchNodeBuilder &B, + NodeBuilder &B, ExprEngine &Eng) { for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { CheckBranchConditionFunc fn = BranchConditionCheckers[i]; diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index d1c1e39d59..91aa9a567c 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -602,21 +602,6 @@ StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc, return NULL; } -// This function generate a new ExplodedNode but not a new branch(block edge). -// Creates a transition from the Builder's top predecessor. -ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition, - const ProgramState *State, - const ProgramPointTag *Tag, - bool MarkAsSink) { - ProgramPoint PP = PostCondition(Condition, - BuilderPred->getLocationContext(), Tag); - ExplodedNode *N = generateNodeImpl(PP, State, BuilderPred, MarkAsSink); - assert(N); - // TODO: This needs to go - we should not change Pred!!! - BuilderPred = N; - return N; -} - ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State, bool branch, ExplodedNode *NodePred) { diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index dba1ce10bd..70142c8fc1 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -945,11 +945,9 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, const CFGBlock *DstT, const CFGBlock *DstF) { - BranchNodeBuilder builder(BldCtx, Pred, DstT, DstF); - // Check for NULL conditions; e.g. "for(;;)" if (!Condition) { - BranchNodeBuilder NullCondBldr(BldCtx, Pred, DstT, DstF); + BranchNodeBuilder NullCondBldr(Pred, BldCtx, DstT, DstF); NullCondBldr.markInfeasible(false); Engine.enqueue(NullCondBldr); return; @@ -959,27 +957,36 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, Condition->getLocStart(), "Error evaluating branch"); - //TODO: This should take the NodeBuiolder. - getCheckerManager().runCheckersForBranchCondition(Condition, builder, + NodeBuilder CheckerBldr(Pred, BldCtx); + getCheckerManager().runCheckersForBranchCondition(Condition, CheckerBldr, *this); - const ProgramState *PrevState = builder.getState(); - SVal X = PrevState->getSVal(Condition); - - if (X.isUnknownOrUndef()) { - // Give it a chance to recover from unknown. - if (const Expr *Ex = dyn_cast<Expr>(Condition)) { - if (Ex->getType()->isIntegerType()) { - // Try to recover some path-sensitivity. Right now casts of symbolic - // integers that promote their values are currently not tracked well. - // If 'Condition' is such an expression, try and recover the - // underlying value and use that instead. - SVal recovered = RecoverCastedSymbol(getStateManager(), - builder.getState(), Condition, - getContext()); - - if (!recovered.isUnknown()) { - X = recovered; + for (NodeBuilder::iterator I = CheckerBldr.results_begin(), + E = CheckerBldr.results_end(); E != I; ++I) { + ExplodedNode *PredI = *I; + + if (PredI->isSink()) + continue; + + BranchNodeBuilder builder(PredI, BldCtx, DstT, DstF); + const ProgramState *PrevState = builder.getState(); + SVal X = PrevState->getSVal(Condition); + + if (X.isUnknownOrUndef()) { + // Give it a chance to recover from unknown. + if (const Expr *Ex = dyn_cast<Expr>(Condition)) { + if (Ex->getType()->isIntegerType()) { + // Try to recover some path-sensitivity. Right now casts of symbolic + // integers that promote their values are currently not tracked well. + // If 'Condition' is such an expression, try and recover the + // underlying value and use that instead. + SVal recovered = RecoverCastedSymbol(getStateManager(), + PrevState, Condition, + getContext()); + + if (!recovered.isUnknown()) { + X = recovered; + } } } } @@ -989,30 +996,30 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, builder.generateNode(MarkBranch(PrevState, Term, false), false); // Enqueue the results into the work list. Engine.enqueue(builder); - return; + continue; } - } - DefinedSVal V = cast<DefinedSVal>(X); + DefinedSVal V = cast<DefinedSVal>(X); - // Process the true branch. - if (builder.isFeasible(true)) { - if (const ProgramState *state = PrevState->assume(V, true)) - builder.generateNode(MarkBranch(state, Term, true), true); - else - builder.markInfeasible(true); - } + // Process the true branch. + if (builder.isFeasible(true)) { + if (const ProgramState *state = PrevState->assume(V, true)) + builder.generateNode(MarkBranch(state, Term, true), true); + else + builder.markInfeasible(true); + } - // Process the false branch. - if (builder.isFeasible(false)) { - if (const ProgramState *state = PrevState->assume(V, false)) - builder.generateNode(MarkBranch(state, Term, false), false); - else - builder.markInfeasible(false); - } + // Process the false branch. + if (builder.isFeasible(false)) { + if (const ProgramState *state = PrevState->assume(V, false)) + builder.generateNode(MarkBranch(state, Term, false), false); + else + builder.markInfeasible(false); + } - // Enqueue the results into the work list. - Engine.enqueue(builder); + // Enqueue the results into the work list. + Engine.enqueue(builder); + } } /// processIndirectGoto - Called by CoreEngine. Used to generate successor |