[cfe-commits] r126724 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/StaticAnalyzer/Checkers/ExprEngine.cpp lib/StaticAnalyzer/Core/CFRefCount.cpp lib/StaticAnalyzer/Core/CXXExprEngine.cpp
Argyrios Kyrtzidis
akyrtzi at gmail.com
Mon Feb 28 17:16:03 PST 2011
Author: akirtzidis
Date: Mon Feb 28 19:16:03 2011
New Revision: 126724
URL: http://llvm.org/viewvc/llvm-project?rev=126724&view=rev
Log:
[analyzer] Remove checker V1 registration and running from ExprEngine.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp
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=126724&r1=126723&r2=126724&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Mon Feb 28 19:16:03 2011
@@ -74,39 +74,6 @@
Selector* NSExceptionInstanceRaiseSelectors;
Selector RaiseSel;
- enum CallbackKind {
- PreVisitStmtCallback,
- PostVisitStmtCallback,
- processAssumeCallback,
- EvalRegionChangesCallback
- };
-
- typedef uint32_t CallbackTag;
-
- /// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub'
- /// argument can be used to differentiate callbacks that depend on another
- /// value from a small set of possibilities, such as statement classes.
- static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) {
- assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits");
- return K | (Sub << 8);
- }
-
- typedef llvm::DenseMap<void *, unsigned> CheckerMap;
- typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered;
- typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache;
-
- /// A registration map from checker tag to the index into the
- /// ordered checkers vector.
- CheckerMap CheckerM;
-
- /// An ordered vector of checkers that are called when evaluating
- /// various expressions and statements.
- CheckersOrdered Checkers;
-
- /// A map used for caching the checkers that respond to the callback for
- /// a particular callback tag.
- CheckersOrderedCache COCache;
-
/// The BugReporter associated with this engine. It is important that
/// this object be placed at the very end of member variables so that its
/// destructor is called before the rest of the ExprEngine is destroyed.
@@ -165,21 +132,6 @@
ExplodedGraph& getGraph() { return G; }
const ExplodedGraph& getGraph() const { return G; }
- template <typename CHECKER>
- void registerCheck(CHECKER *check) {
- unsigned entry = Checkers.size();
- void *tag = CHECKER::getTag();
- Checkers.push_back(std::make_pair(tag, check));
- CheckerM[tag] = entry;
- }
-
- Checker *lookupChecker(void *tag) const;
-
- template <typename CHECKER>
- CHECKER *getChecker() const {
- return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
- }
-
/// processCFGElement - Called by CoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a CFG element.
void processCFGElement(const CFGElement E, StmtNodeBuilder& builder);
@@ -281,27 +233,6 @@
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0);
- /// CheckerVisit - Dispatcher for performing checker-specific logic
- /// at specific statements.
- void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- CallbackKind Kind);
-
- void CheckerVisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src, bool isPrevisit);
-
- bool CheckerEvalCall(const CallExpr *CE,
- ExplodedNodeSet &Dst,
- ExplodedNode *Pred);
-
- void CheckerEvalNilReceiver(const ObjCMessage &msg,
- ExplodedNodeSet &Dst,
- const GRState *state,
- ExplodedNode *Pred);
-
- void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src, SVal location, SVal val,
- bool isPrevisit);
-
/// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements.
void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?rev=126724&r1=126723&r2=126724&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp Mon Feb 28 19:16:03 2011
@@ -60,248 +60,6 @@
}
//===----------------------------------------------------------------------===//
-// Checker worklist routines.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src, CallbackKind Kind) {
-
- // Determine if we already have a cached 'CheckersOrdered' vector
- // specifically tailored for the provided <CallbackKind, Stmt kind>. This
- // can reduce the number of checkers actually called.
- CheckersOrdered *CO = &Checkers;
- llvm::OwningPtr<CheckersOrdered> NewCO;
-
- // The cache key is made up of the and the callback kind (pre- or post-visit)
- // and the statement kind.
- CallbackTag K = GetCallbackTag(Kind, S->getStmtClass());
-
- CheckersOrdered *& CO_Ref = COCache[K];
-
- if (!CO_Ref) {
- // If we have no previously cached CheckersOrdered vector for this
- // statement kind, then create one.
- NewCO.reset(new CheckersOrdered);
- }
- else {
- // Use the already cached set.
- CO = CO_Ref;
- }
-
- if (CO->empty()) {
- // If there are no checkers, just delegate to the checker manager.
- getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback,
- Dst, Src, S, *this);
- return;
- }
-
- ExplodedNodeSet CheckersV1Dst;
- ExplodedNodeSet Tmp;
- ExplodedNodeSet *PrevSet = &Src;
- unsigned checkersEvaluated = 0;
-
- for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I) {
- // If all nodes are sunk, bail out early.
- if (PrevSet->empty())
- break;
- ExplodedNodeSet *CurrSet = 0;
- if (I+1 == E)
- CurrSet = &CheckersV1Dst;
- else {
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
- CurrSet->clear();
- }
- void *tag = I->first;
- Checker *checker = I->second;
- bool respondsToCallback = true;
-
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI) {
-
- checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag,
- Kind == PreVisitStmtCallback, respondsToCallback);
-
- }
-
- PrevSet = CurrSet;
-
- if (NewCO.get()) {
- ++checkersEvaluated;
- if (respondsToCallback)
- NewCO->push_back(*I);
- }
- }
-
- // If we built NewCO, check if we called all the checkers. This is important
- // so that we know that we accurately determined the entire set of checkers
- // that responds to this callback. Note that 'checkersEvaluated' might
- // not be the same as Checkers.size() if one of the Checkers generates
- // a sink node.
- if (NewCO.get() && checkersEvaluated == Checkers.size())
- CO_Ref = NewCO.take();
-
- // Don't autotransition. The CheckerContext objects should do this
- // automatically.
-
- getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback,
- Dst, CheckersV1Dst, S, *this);
-}
-
-void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
- ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src,
- bool isPrevisit) {
-
- if (Checkers.empty()) {
- getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, Src, msg,
- *this);
- return;
- }
-
- ExplodedNodeSet CheckersV1Dst;
- ExplodedNodeSet Tmp;
- ExplodedNodeSet *PrevSet = &Src;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
- {
- ExplodedNodeSet *CurrSet = 0;
- if (I+1 == E)
- CurrSet = &CheckersV1Dst;
- else {
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
- CurrSet->clear();
- }
-
- void *tag = I->first;
- Checker *checker = I->second;
-
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI)
- checker->GR_visitObjCMessage(*CurrSet, *Builder, *this, msg,
- *NI, tag, isPrevisit);
-
- // Update which NodeSet is the current one.
- PrevSet = CurrSet;
- }
-
- getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, CheckersV1Dst,
- msg, *this);
-}
-
-void ExprEngine::CheckerEvalNilReceiver(const ObjCMessage &msg,
- ExplodedNodeSet &Dst,
- const GRState *state,
- ExplodedNode *Pred) {
- bool evaluated = false;
- ExplodedNodeSet DstTmp;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
- void *tag = I->first;
- Checker *checker = I->second;
-
- if (checker->GR_evalNilReceiver(DstTmp, *Builder, *this, msg, Pred, state,
- tag)) {
- evaluated = true;
- break;
- } else
- // The checker didn't evaluate the expr. Restore the Dst.
- DstTmp.clear();
- }
-
- if (evaluated)
- Dst.insert(DstTmp);
- else
- Dst.insert(Pred);
-}
-
-// CheckerEvalCall returns true if one of the checkers processed the node.
-// This may return void when all call evaluation logic goes to some checker
-// in the future.
-bool ExprEngine::CheckerEvalCall(const CallExpr *CE,
- ExplodedNodeSet &Dst,
- ExplodedNode *Pred) {
- bool evaluated = false;
- ExplodedNodeSet DstTmp;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
- void *tag = I->first;
- Checker *checker = I->second;
-
- if (checker->GR_evalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) {
- evaluated = true;
- break;
- } else
- // The checker didn't evaluate the expr. Restore the DstTmp set.
- DstTmp.clear();
- }
-
- if (evaluated) {
- Dst.insert(DstTmp);
- return evaluated;
- }
-
- class DefaultEval : public GraphExpander {
- bool &Evaluated;
- public:
- DefaultEval(bool &evaluated) : Evaluated(evaluated) { }
- virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
- Evaluated = false;
- Dst.insert(Pred);
- }
- };
-
- evaluated = true;
- DefaultEval defaultEval(evaluated);
- getCheckerManager().runCheckersForEvalCall(Dst, Pred, CE, *this,
- &defaultEval);
- return evaluated;
-}
-
-// FIXME: This is largely copy-paste from CheckerVisit(). Need to
-// unify.
-void ExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src, SVal location,
- SVal val, bool isPrevisit) {
-
- if (Checkers.empty()) {
- getCheckerManager().runCheckersForBind(Dst, Src, location, val, StoreE,
- *this);
- return;
- }
-
- ExplodedNodeSet CheckerV1Tmp;
- ExplodedNodeSet Tmp;
- ExplodedNodeSet *PrevSet = &Src;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
- {
- ExplodedNodeSet *CurrSet = 0;
- if (I+1 == E)
- CurrSet = &CheckerV1Tmp;
- else {
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
- CurrSet->clear();
- }
-
- void *tag = I->first;
- Checker *checker = I->second;
-
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI)
- checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE,
- *NI, tag, location, val, isPrevisit);
-
- // Update which NodeSet is the current one.
- PrevSet = CurrSet;
- }
-
- getCheckerManager().runCheckersForBind(Dst, CheckerV1Tmp, location, val,
- StoreE, *this);
-
- // Don't autotransition. The CheckerContext objects should do this
- // automatically.
-}
-//===----------------------------------------------------------------------===//
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
@@ -333,14 +91,6 @@
ExprEngine::~ExprEngine() {
BR.FlushReports();
delete [] NSExceptionInstanceRaiseSelectors;
-
- // Delete the set of checkers.
- for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
- delete I->second;
-
- for (CheckersOrderedCache::iterator I=COCache.begin(), E=COCache.end();
- I!=E;++I)
- delete I->second;
}
//===----------------------------------------------------------------------===//
@@ -415,52 +165,6 @@
/// logic for handling assumptions on symbolic values.
const GRState *ExprEngine::processAssume(const GRState *state, SVal cond,
bool assumption) {
- // Determine if we already have a cached 'CheckersOrdered' vector
- // specifically tailored for processing assumptions. This
- // can reduce the number of checkers actually called.
- CheckersOrdered *CO = &Checkers;
- llvm::OwningPtr<CheckersOrdered> NewCO;
-
- CallbackTag K = GetCallbackTag(processAssumeCallback);
- CheckersOrdered *& CO_Ref = COCache[K];
-
- if (!CO_Ref) {
- // If we have no previously cached CheckersOrdered vector for this
- // statement kind, then create one.
- NewCO.reset(new CheckersOrdered);
- }
- else {
- // Use the already cached set.
- CO = CO_Ref;
- }
-
- if (!CO->empty()) {
- // Let the checkers have a crack at the assume before the transfer functions
- // get their turn.
- for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I!=E; ++I) {
-
- // If any checker declares the state infeasible (or if it starts that
- // way), bail out.
- if (!state)
- return NULL;
-
- Checker *C = I->second;
- bool respondsToCallback = true;
-
- state = C->evalAssume(state, cond, assumption, &respondsToCallback);
-
- // Check if we're building the cache of checkers that care about
- // assumptions.
- if (NewCO.get() && respondsToCallback)
- NewCO->push_back(*I);
- }
-
- // If we got through all the checkers, and we built a list of those that
- // care about assumptions, save it.
- if (NewCO.get())
- CO_Ref = NewCO.take();
- }
-
state = getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
// If the state is infeasible at this point, bail out.
@@ -471,18 +175,6 @@
}
bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) {
- CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
- CheckersOrdered *CO = COCache[K];
-
- if (!CO)
- CO = &Checkers;
-
- for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
- Checker *C = I->second;
- if (C->wantsRegionChangeUpdate(state))
- return true;
- }
-
return getCheckerManager().wantsRegionChangeUpdate(state);
}
@@ -490,60 +182,10 @@
ExprEngine::processRegionChanges(const GRState *state,
const MemRegion * const *Begin,
const MemRegion * const *End) {
- // FIXME: Most of this method is copy-pasted from processAssume.
-
- // Determine if we already have a cached 'CheckersOrdered' vector
- // specifically tailored for processing region changes. This
- // can reduce the number of checkers actually called.
- CheckersOrdered *CO = &Checkers;
- llvm::OwningPtr<CheckersOrdered> NewCO;
-
- CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
- CheckersOrdered *& CO_Ref = COCache[K];
-
- if (!CO_Ref) {
- // If we have no previously cached CheckersOrdered vector for this
- // callback, then create one.
- NewCO.reset(new CheckersOrdered);
- }
- else {
- // Use the already cached set.
- CO = CO_Ref;
- }
-
- // If there are no checkers, just delegate to the checker manager.
- if (CO->empty())
- return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
-
- for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
- // If any checker declares the state infeasible (or if it starts that way),
- // bail out.
- if (!state)
- return NULL;
-
- Checker *C = I->second;
- bool respondsToCallback = true;
-
- state = C->EvalRegionChanges(state, Begin, End, &respondsToCallback);
-
- // See if we're building a cache of checkers that care about region changes.
- if (NewCO.get() && respondsToCallback)
- NewCO->push_back(*I);
- }
-
- // If we got through all the checkers, and we built a list of those that
- // care about region changes, save it.
- if (NewCO.get())
- CO_Ref = NewCO.take();
-
return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
}
void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
- I->second->VisitEndAnalysis(G, BR, *this);
- }
getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
}
@@ -585,13 +227,6 @@
if (AMgr.shouldPurgeDead()) {
const GRState *St = EntryNode->getState();
-
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
- Checker *checker = I->second;
- checker->MarkLiveSymbols(St, SymReaper);
- }
-
getCheckerManager().runCheckersForLiveSymbols(St, SymReaper);
const StackFrameContext *SFC = LC->getCurrentStackFrame();
@@ -617,33 +252,7 @@
getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
CleanedState, SymReaper);
- ExplodedNodeSet checkersV1Tmp;
- if (Checkers.empty())
- checkersV1Tmp.insert(Tmp2);
- else {
- ExplodedNodeSet Tmp3;
- ExplodedNodeSet *SrcSet = &Tmp2;
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
- ExplodedNodeSet *DstSet = 0;
- if (I+1 == E)
- DstSet = &checkersV1Tmp;
- else {
- DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2;
- DstSet->clear();
- }
-
- void *tag = I->first;
- Checker *checker = I->second;
- for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();
- NI != NE; ++NI)
- checker->GR_evalDeadSymbols(*DstSet, *Builder, *this, currentStmt,
- *NI, SymReaper, tag);
- SrcSet = DstSet;
- }
- }
-
- getCheckerManager().runCheckersForDeadSymbols(Tmp, checkersV1Tmp,
+ getCheckerManager().runCheckersForDeadSymbols(Tmp, Tmp2,
SymReaper, currentStmt, *this);
if (!Builder->BuildSinks && !Builder->hasGeneratedNode)
@@ -1283,12 +892,6 @@
Condition->getLocStart(),
"Error evaluating branch");
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
- void *tag = I->first;
- Checker *checker = I->second;
- checker->VisitBranchCondition(builder, *this, Condition, tag);
- }
-
getCheckerManager().runCheckersForBranchCondition(Condition, builder, *this);
// If the branch condition is undefined, return;
@@ -1413,12 +1016,6 @@
void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
getTF().evalEndPath(*this, builder);
StateMgr.EndPath(builder.getState());
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
- void *tag = I->first;
- Checker *checker = I->second;
- EndOfFunctionNodeBuilder B = builder.withCheckerTag(tag);
- checker->evalEndPath(B, tag, *this);
- }
getCheckerManager().runCheckersForEndPath(builder, *this);
}
@@ -1638,7 +1235,7 @@
ProgramPoint::PostLValueKind);
// Post-visit the BlockExpr.
- CheckerVisit(BE, Dst, Tmp, PostVisitStmtCallback);
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
}
void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
@@ -1695,7 +1292,7 @@
ExplodedNodeSet Tmp2;
Visit(Idx, *I1, Tmp2); // Evaluate the index.
ExplodedNodeSet Tmp3;
- CheckerVisit(A, Tmp3, Tmp2, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(Tmp3, Tmp2, A, *this);
for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) {
const GRState* state = GetState(*I2);
@@ -1756,7 +1353,8 @@
// Do a previsit of the bind.
ExplodedNodeSet CheckedSet, Src;
Src.Add(Pred);
- CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true);
+ getCheckerManager().runCheckersForBind(CheckedSet, Src, location, Val, StoreE,
+ *this);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
@@ -1929,53 +1527,23 @@
return;
}
- if (Checkers.empty()) {
- ExplodedNodeSet Src;
- if (Builder->GetState(Pred) == state) {
- Src.Add(Pred);
- } else {
- // Associate this new state with an ExplodedNode.
- Src.Add(Builder->generateNode(S, state, Pred));
- }
- getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S,
- *this);
- return;
- }
-
ExplodedNodeSet Src;
- Src.Add(Pred);
- ExplodedNodeSet CheckersV1Dst;
- ExplodedNodeSet Tmp;
- ExplodedNodeSet *PrevSet = &Src;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
- {
- ExplodedNodeSet *CurrSet = 0;
- if (I+1 == E)
- CurrSet = &CheckersV1Dst;
- else {
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
- CurrSet->clear();
- }
-
- void *tag = I->first;
- Checker *checker = I->second;
-
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI) {
- // Use the 'state' argument only when the predecessor node is the
- // same as Pred. This allows us to catch updates to the state.
- checker->GR_visitLocation(*CurrSet, *Builder, *this, S, *NI,
- *NI == Pred ? state : GetState(*NI),
- location, tag, isLoad);
- }
-
- // Update which NodeSet is the current one.
- PrevSet = CurrSet;
+ if (Builder->GetState(Pred) == state) {
+ Src.Add(Pred);
+ } else {
+ // Associate this new state with an ExplodedNode.
+ // FIXME: If I pass null tag, the graph is incorrect, e.g for
+ // int *p;
+ // p = 0;
+ // *p = 0xDEADBEEF;
+ // "p = 0" is not noted as "Null pointer value stored to 'p'" but
+ // instead "int *p" is noted as
+ // "Variable 'p' initialized to a null pointer value"
+ ExplodedNode *N = Builder->generateNode(S, state, Pred, this);
+ Src.Add(N ? N : Pred);
}
-
- getCheckerManager().runCheckersForLocation(Dst, CheckersV1Dst, location,
- isLoad, S, *this);
+ getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S,
+ *this);
}
bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
@@ -2044,58 +1612,59 @@
ExplodedNodeSet DstTmp2;
Visit(Callee, *NI, DstTmp2);
// Perform the previsit of the CallExpr, storing the results in DstTmp.
- CheckerVisit(CE, DstTmp, DstTmp2, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(DstTmp, DstTmp2, CE, *this);
}
- // Finally, evaluate the function call. We try each of the checkers
- // to see if the can evaluate the function call.
- ExplodedNodeSet DstTmp3;
-
- for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
- DI != DE; ++DI) {
-
- const GRState* state = GetState(*DI);
- SVal L = state->getSVal(Callee);
-
- // FIXME: Add support for symbolic function calls (calls involving
- // function pointer values that are symbolic).
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- ExplodedNodeSet DstChecker;
-
- // If the callee is processed by a checker, skip the rest logic.
- if (CheckerEvalCall(CE, DstChecker, *DI))
- DstTmp3.insert(DstChecker);
- else if (AMgr.shouldInlineCall() && InlineCall(Dst, CE, *DI)) {
- // Callee is inlined. We shouldn't do post call checking.
- return;
- }
- else {
- for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(),
- DE_Checker = DstChecker.end();
- DI_Checker != DE_Checker; ++DI_Checker) {
+ class DefaultEval : public GraphExpander {
+ ExprEngine &Eng;
+ const CallExpr *CE;
+ public:
+ bool Inlined;
+
+ DefaultEval(ExprEngine &eng, const CallExpr *ce)
+ : Eng(eng), CE(ce), Inlined(false) { }
+ virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ if (Eng.getAnalysisManager().shouldInlineCall() &&
+ Eng.InlineCall(Dst, CE, Pred)) {
+ Inlined = true;
+ } else {
+ StmtNodeBuilder &Builder = Eng.getBuilder();
+ assert(&Builder && "StmtNodeBuilder must be defined.");
// Dispatch to the plug-in transfer function.
- unsigned oldSize = DstTmp3.size();
- SaveOr OldHasGen(Builder->hasGeneratedNode);
- Pred = *DI_Checker;
+ unsigned oldSize = Dst.size();
+ SaveOr OldHasGen(Builder.hasGeneratedNode);
// Dispatch to transfer function logic to handle the call itself.
- // FIXME: Allow us to chain together transfer functions.
- assert(Builder && "StmtNodeBuilder must be defined.");
- getTF().evalCall(DstTmp3, *this, *Builder, CE, L, Pred);
+ const Expr* Callee = CE->getCallee()->IgnoreParens();
+ const GRState* state = Eng.GetState(Pred);
+ SVal L = state->getSVal(Callee);
+ Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, Pred);
// Handle the case where no nodes where generated. Auto-generate that
// contains the updated state if we aren't generating sinks.
- if (!Builder->BuildSinks && DstTmp3.size() == oldSize &&
- !Builder->hasGeneratedNode)
- MakeNode(DstTmp3, CE, Pred, state);
+ if (!Builder.BuildSinks && Dst.size() == oldSize &&
+ !Builder.hasGeneratedNode)
+ Eng.MakeNode(Dst, CE, Pred, state);
}
}
- }
+ };
+
+ // Finally, evaluate the function call. We try each of the checkers
+ // to see if the can evaluate the function call.
+ ExplodedNodeSet DstTmp3;
+ DefaultEval defEval(*this, CE);
+
+ getCheckerManager().runCheckersForEvalCall(DstTmp3, DstTmp, CE,
+ *this, &defEval);
+
+ // Callee is inlined. We shouldn't do post call checking.
+ if (defEval.Inlined)
+ return;
// Finally, perform the post-condition check of the CallExpr and store
// the created nodes in 'Dst'.
- CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback);
+ getCheckerManager().runCheckersForPostStmt(Dst, DstTmp3, CE, *this);
}
//===----------------------------------------------------------------------===//
@@ -2187,7 +1756,7 @@
// Pre-visit the ObjCAtSynchronizedStmt.
ExplodedNodeSet Tmp;
Tmp.Add(Pred);
- CheckerVisit(S, Dst, Tmp, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(Dst, Tmp, S, *this);
}
//===----------------------------------------------------------------------===//
@@ -2218,7 +1787,7 @@
// Perform the post-condition check of the ObjCIvarRefExpr and store
// the created nodes in 'Dst'.
- CheckerVisit(Ex, Dst, dstIvar, PostVisitStmtCallback);
+ getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
}
//===----------------------------------------------------------------------===//
@@ -2388,7 +1957,7 @@
// Handle the previsits checks.
ExplodedNodeSet DstPrevisit;
- CheckerVisitObjCMessage(msg, DstPrevisit, Src, /*isPreVisit=*/true);
+ getCheckerManager().runCheckersForPreObjCMessage(DstPrevisit, Src, msg,*this);
// Proceed with evaluate the message expression.
ExplodedNodeSet dstEval;
@@ -2413,9 +1982,9 @@
llvm::tie(notNilState, nilState) = state->assume(receiverVal);
// There are three cases: can be nil or non-nil, must be nil, must be
- // non-nil. We handle must be nil, and merge the rest two into non-nil.
+ // non-nil. We ignore must be nil, and merge the rest two into non-nil.
if (nilState && !notNilState) {
- CheckerEvalNilReceiver(msg, dstEval, nilState, Pred);
+ dstEval.insert(Pred);
continue;
}
@@ -2491,7 +2060,7 @@
// Finally, perform the post-condition check of the ObjCMessageExpr and store
// the created nodes in 'Dst'.
- CheckerVisitObjCMessage(msg, Dst, dstEval, /*isPreVisit=*/false);
+ getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this);
}
//===----------------------------------------------------------------------===//
@@ -2504,7 +2073,7 @@
ExplodedNodeSet S1;
Visit(Ex, Pred, S1);
ExplodedNodeSet S2;
- CheckerVisit(CastE, S2, S1, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(S2, S1, CastE, *this);
if (CastE->getCastKind() == CK_LValueToRValue ||
CastE->getCastKind() == CK_GetObjCProperty) {
@@ -2677,7 +2246,7 @@
Tmp.Add(Pred);
ExplodedNodeSet Tmp2;
- CheckerVisit(DS, Tmp2, Tmp, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(Tmp2, Tmp, DS, *this);
for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) {
ExplodedNode *N = *I;
@@ -3238,7 +2807,7 @@
}
ExplodedNodeSet CheckedSet;
- CheckerVisit(RS, CheckedSet, Src, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(CheckedSet, Src, RS, *this);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I != E; ++I) {
@@ -3280,7 +2849,7 @@
Visit(RHS, *I1, Tmp2);
ExplodedNodeSet CheckedSet;
- CheckerVisit(B, CheckedSet, Tmp2, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(CheckedSet, Tmp2, B, *this);
// With both the LHS and RHS evaluated, process the operation itself.
@@ -3407,16 +2976,7 @@
}
}
- CheckerVisit(B, Dst, Tmp3, PostVisitStmtCallback);
-}
-
-//===----------------------------------------------------------------------===//
-// Checker registration/lookup.
-//===----------------------------------------------------------------------===//
-
-Checker *ExprEngine::lookupChecker(void *tag) const {
- CheckerMap::const_iterator I = CheckerM.find(tag);
- return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp3, B, *this);
}
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp?rev=126724&r1=126723&r2=126724&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp Mon Feb 28 19:16:03 2011
@@ -12,6 +12,9 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/LangOptions.h"
@@ -20,7 +23,6 @@
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
@@ -3395,19 +3397,15 @@
namespace {
class RetainReleaseChecker
- : public CheckerVisitor<RetainReleaseChecker> {
- CFRefCount *TF;
+ : public CheckerV2< check::PostStmt<BlockExpr> > {
public:
- RetainReleaseChecker(CFRefCount *tf) : TF(tf) {}
- static void* getTag() { static int x = 0; return &x; }
-
- void PostVisitBlockExpr(CheckerContext &C, const BlockExpr *BE);
+ void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
};
} // end anonymous namespace
-void RetainReleaseChecker::PostVisitBlockExpr(CheckerContext &C,
- const BlockExpr *BE) {
+void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE,
+ CheckerContext &C) const {
// Scan the BlockDecRefExprs for any object the retain/release checker
// may be tracking.
@@ -3510,7 +3508,9 @@
// Register the RetainReleaseChecker with the ExprEngine object.
// Functionality in CFRefCount will be migrated to RetainReleaseChecker
// over time.
- Eng.registerCheck(new RetainReleaseChecker(this));
+ // FIXME: HACK! Remove TransferFuncs and turn all of CFRefCount into fully
+ // using the checker mechanism.
+ Eng.getCheckerManager().registerChecker<RetainReleaseChecker>();
}
TransferFuncs* ento::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp?rev=126724&r1=126723&r2=126724&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp Mon Feb 28 19:16:03 2011
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/AST/DeclCXX.h"
@@ -224,11 +225,11 @@
ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
// Allow checkers to pre-visit the member call.
ExplodedNodeSet PreVisitChecks;
- CheckerVisit(MCE, PreVisitChecks, Src, PreVisitStmtCallback);
+ getCheckerManager().runCheckersForPreStmt(PreVisitChecks, Src, MCE, *this);
if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
// FIXME: conservative method call evaluation.
- CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback);
+ getCheckerManager().runCheckersForPostStmt(Dst, PreVisitChecks, MCE, *this);
return;
}
More information about the cfe-commits
mailing list