зеркало из https://github.com/microsoft/clang-1.git
[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:
Родитель
f0cc2087b1
Коммит
3070e13dca
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче