[analyzer] Remove CallEnterNodeBuilder and simplify ExprEngine::processCallEnter().

This removes analysis of other translation units, but that was an experimental feature anyway that we will revisit later.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147705 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2012-01-07 01:03:17 +00:00
Родитель f0cc2087b1
Коммит 3070e13dca
6 изменённых файлов: 33 добавлений и 133 удалений

Просмотреть файл

@ -46,8 +46,6 @@ class CoreEngine {
friend class IndirectGotoNodeBuilder;
friend class SwitchNodeBuilder;
friend class EndOfFunctionNodeBuilder;
friend class CallEnterNodeBuilder;
public:
typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
BlocksExhausted;
@ -91,9 +89,6 @@ private:
void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
ExplodedNode *Pred);
void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred);
void HandleCallExit(const CallExit &L, ExplodedNode *Pred);
private:
CoreEngine(const CoreEngine&); // Do not implement.
@ -528,49 +523,7 @@ public:
}
};
class CallEnterNodeBuilder {
CoreEngine &Eng;
const ExplodedNode *Pred;
// The call site. For implicit automatic object dtor, this is the trigger
// statement.
const Stmt *CE;
// The context of the callee.
const StackFrameContext *CalleeCtx;
// The parent block of the CallExpr.
const CFGBlock *Block;
// The CFGBlock index of the CallExpr.
unsigned Index;
public:
CallEnterNodeBuilder(CoreEngine &eng, const ExplodedNode *pred,
const Stmt *s, const StackFrameContext *callee,
const CFGBlock *blk, unsigned idx)
: Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
const ProgramState *getState() const { return Pred->getState(); }
const LocationContext *getLocationContext() const {
return Pred->getLocationContext();
}
const Stmt *getCallExpr() const { return CE; }
const StackFrameContext *getCalleeContext() const { return CalleeCtx; }
const CFGBlock *getBlock() const { return Block; }
unsigned getIndex() const { return Index; }
void generateNode(const ProgramState *state);
};
} // end GR namespace
} // end ento namespace
} // end clang namespace
#endif

Просмотреть файл

@ -185,7 +185,7 @@ public:
void processEndOfFunction(NodeBuilderContext& BC);
/// Generate the entry node of the callee.
void processCallEnter(CallEnterNodeBuilder &builder);
void processCallEnter(CallEnter CE, ExplodedNode *Pred);
/// Generate the first post callsite node.
void processCallExit(ExplodedNode *Pred);

Просмотреть файл

@ -37,7 +37,6 @@ class BranchNodeBuilder;
class IndirectGotoNodeBuilder;
class SwitchNodeBuilder;
class EndOfFunctionNodeBuilder;
class CallEnterNodeBuilder;
class NodeBuilderWithSinks;
class MemRegion;
@ -84,7 +83,7 @@ public:
virtual void processEndOfFunction(NodeBuilderContext& BC) = 0;
// Generate the entry node of the callee.
virtual void processCallEnter(CallEnterNodeBuilder &builder) = 0;
virtual void processCallEnter(CallEnter CE, ExplodedNode *Pred) = 0;
// Generate the first post callsite node.
virtual void processCallExit(ExplodedNode *Pred) = 0;

Просмотреть файл

@ -215,12 +215,11 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
break;
case ProgramPoint::CallEnterKind:
HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(),
WU.getIndex(), Node);
SubEng.processCallEnter(cast<CallEnter>(Node->getLocation()), Node);
break;
case ProgramPoint::CallExitKind:
HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
SubEng.processCallExit(Node);
break;
default:
@ -246,17 +245,6 @@ void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
}
}
void CoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred) {
CallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
L.getCalleeContext(), Block, Index);
SubEng.processCallEnter(Builder);
}
void CoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
SubEng.processCallExit(Pred);
}
void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
const CFGBlock *Blk = L.getDst();
@ -644,65 +632,3 @@ SwitchNodeBuilder::generateDefaultCaseNode(const ProgramState *St,
return Succ;
}
void CallEnterNodeBuilder::generateNode(const ProgramState *state) {
// Check if the callee is in the same translation unit.
if (CalleeCtx->getTranslationUnit() !=
Pred->getLocationContext()->getTranslationUnit()) {
// Create a new engine. We must be careful that the new engine should not
// reference data structures owned by the old engine.
AnalysisManager &OldMgr = Eng.SubEng.getAnalysisManager();
// Get the callee's translation unit.
idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
// Create a new AnalysisManager with components of the callee's
// TranslationUnit.
// The Diagnostic is actually shared when we create ASTUnits from AST files.
AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(), OldMgr);
// Create the new engine.
// FIXME: This cast isn't really safe.
bool GCEnabled = static_cast<ExprEngine&>(Eng.SubEng).isObjCGCEnabled();
ExprEngine NewEng(AMgr, GCEnabled);
// Create the new LocationContext.
AnalysisDeclContext *NewAnaCtx =
AMgr.getAnalysisDeclContext(CalleeCtx->getDecl(),
CalleeCtx->getTranslationUnit());
const StackFrameContext *OldLocCtx = CalleeCtx;
const StackFrameContext *NewLocCtx =
NewAnaCtx->getStackFrame(OldLocCtx->getParent(),
OldLocCtx->getCallSite(),
OldLocCtx->getCallSiteBlock(),
OldLocCtx->getIndex());
// Now create an initial state for the new engine.
const ProgramState *NewState =
NewEng.getStateManager().MarshalState(state, NewLocCtx);
ExplodedNodeSet ReturnNodes;
NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
NewState, ReturnNodes);
return;
}
// Get the callee entry block.
const CFGBlock *Entry = &(CalleeCtx->getCFG()->getEntry());
assert(Entry->empty());
assert(Entry->succ_size() == 1);
// Get the solitary successor.
const CFGBlock *SuccB = *(Entry->succ_begin());
// Construct an edge representing the starting location in the callee.
BlockEdge Loc(Entry, SuccB, CalleeCtx);
bool isNew;
ExplodedNode *Node = Eng.G->getNode(Loc, state, false, &isNew);
Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
if (isNew)
Eng.WList->enqueue(Node);
}

Просмотреть файл

@ -1616,7 +1616,8 @@ bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
const StackFrameContext *stackFrame =
AMgr.getStackFrame(AMgr.getAnalysisDeclContext(FD),
Pred->getLocationContext(),
CE, currentBuilderContext->getBlock(), currentStmtIdx);
CE, currentBuilderContext->getBlock(),
currentStmtIdx);
// Now we have the definition of the callee, create a CallEnter node.
CallEnter Loc(CE, stackFrame, Pred->getLocationContext());

Просмотреть файл

@ -28,10 +28,32 @@ namespace {
int ReturnExpr::TagInt;
}
void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
const ProgramState *state =
B.getState()->enterStackFrame(B.getCalleeContext());
B.generateNode(state);
void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
// Get the entry block in the CFG of the callee.
const StackFrameContext *SFC = CE.getCalleeContext();
const CFG *CalleeCFG = SFC->getCFG();
const CFGBlock *Entry = &(CalleeCFG->getEntry());
// Validate the CFG.
assert(Entry->empty());
assert(Entry->succ_size() == 1);
// Get the solitary sucessor.
const CFGBlock *Succ = *(Entry->succ_begin());
// Construct an edge representing the starting location in the callee.
BlockEdge Loc(Entry, Succ, SFC);
// Construct a new state which contains the mapping from actual to
// formal arguments.
const ProgramState *state = Pred->getState()->enterStackFrame(SFC);
// Construct a new node and add it to the worklist.
bool isNew;
ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);
Node->addPredecessor(Pred, G);
if (isNew)
Engine.getWorkList()->enqueue(Node);
}
void ExprEngine::processCallExit(ExplodedNode *Pred) {
@ -59,7 +81,6 @@ void ExprEngine::processCallExit(ExplodedNode *Pred) {
// Always bind the region to the CXXConstructExpr.
state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV);
}
PostStmt Loc(CE, calleeCtx->getParent());
bool isNew;