diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 18 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/CheckerContext.cpp | 20 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/CoreEngine.cpp | 38 |
3 files changed, 52 insertions, 24 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 93e0fe5b4f9..be7ce384e7e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -54,12 +54,18 @@ public: GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder &enb) : C(0), tag(0), ENB(&enb) {} - ExplodedNode *MakeNode(const ProgramState *state, ExplodedNode *Pred) { - if (C) - return C->generateNode(state, Pred, tag, false); + ExplodedNode *MakeNode(const ProgramState *state, ExplodedNode *Pred, + bool MarkAsSink = false) { + if (C) { + return C->generateNode(state, Pred, tag, false, MarkAsSink); + } assert(ENB); - return ENB->generateNode(state, Pred); + ExplodedNode *N = ENB->generateNode(state, Pred); + if (MarkAsSink) + N->markAsSink(); + + return N; } }; } // end anonymous namespace @@ -3366,9 +3372,7 @@ RetainCountChecker::handleAutoreleaseCounts(const ProgramState *state, V = V ^ RefVal::ErrorOverAutorelease; state = state->set<RefBindings>(Sym, V); - if (ExplodedNode *N = Bd.MakeNode(state, Pred)) { - N->markAsSink(); - + if (ExplodedNode *N = Bd.MakeNode(state, Pred, true)) { llvm::SmallString<128> sbuf; llvm::raw_svector_ostream os(sbuf); os << "Object over-autoreleased: object was sent -autorelease "; diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index 5356edc752f..e380165c2e8 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -17,17 +17,13 @@ using namespace clang; using namespace ento; CheckerContext::~CheckerContext() { - // Do we need to autotransition? 'Dst' can get populated in a variety of - // ways, including 'addTransition()' adding the predecessor node to Dst - // without actually generated a new node. We also shouldn't autotransition - // if we are building sinks or we generated a node and decided to not - // add it as a transition. - if (Dst.size() == size && !B.BuildSinks && !B.hasGeneratedNode) { - if (ST && ST != Pred->getState()) { - static SimpleProgramPointTag autoTransitionTag("CheckerContext : auto"); - addTransition(ST, &autoTransitionTag); - } - else - Dst.Add(Pred); + // Copy the results into the Dst set. + for (NodeBuilder::iterator I = NB.results_begin(), + E = NB.results_end(); I != E; ++I) { + Dst.Add(*I); } + + // Copy the results into the StmtNodeBuilder. + //TODO: This will be removed after we completely migrate NodeBuilder. + B.importNodesFromBuilder(NB); } diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 525219846a9..5f2f4ea7f17 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -475,11 +475,39 @@ GenericNodeBuilderImpl::generateNodeImpl(const ProgramState *state, return 0; } +NodeBuilder::NodeBuilder(CoreEngine& e, ExplodedNode *N) + : Eng(e), Pred(N), Finalized(false) { + assert(!N->isSink()); + Deferred.insert(N); +} + +ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, + const ProgramState *State, + ExplodedNode *Pred, + bool MarkAsSink) { + assert(Finalized == false && + "We cannot create new nodes after the results have been finalized."); + + bool IsNew; + ExplodedNode *N = Eng.G->getNode(Loc, State, &IsNew); + N->addPredecessor(Pred, *Eng.G); + Deferred.erase(Pred); + + if (MarkAsSink) + N->markAsSink(); + + if (IsNew && !N->isSink()) + Deferred.insert(N); + + return (IsNew ? N : 0); +} + + StmtNodeBuilder::StmtNodeBuilder(const CFGBlock *b, unsigned idx, ExplodedNode *N, CoreEngine* e) - : Eng(*e), B(*b), Idx(idx), Pred(N), + : CommonNodeBuilder(e, N), B(*b), Idx(idx), PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false), PointKind(ProgramPoint::PostStmtKind), Tag(0) { Deferred.insert(N); @@ -574,12 +602,12 @@ StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc, // This function generate a new ExplodedNode but not a new branch(block edge). ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition, - const ProgramState *State) { + const ProgramState *State, + const ProgramPointTag *Tag) { bool IsNew; - ExplodedNode *Succ - = Eng.G->getNode(PostCondition(Condition, Pred->getLocationContext()), State, - &IsNew); + = Eng.G->getNode(PostCondition(Condition, Pred->getLocationContext(), Tag), + State, &IsNew); Succ->addPredecessor(Pred, *Eng.G); |