summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp18
-rw-r--r--clang/lib/StaticAnalyzer/Core/CheckerContext.cpp20
-rw-r--r--clang/lib/StaticAnalyzer/Core/CoreEngine.cpp38
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);
OpenPOWER on IntegriCloud