-//===-- GRConstants.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==//
+//===-- GRExprEngine.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
#include "RValues.h"
#include "ValueState.h"
-#include "clang/Analysis/PathSensitive/GREngine.h"
+#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
namespace {
-class VISIBILITY_HIDDEN GRConstants {
+class VISIBILITY_HIDDEN GRExprEngine {
public:
typedef ValueStateManager::StateTy StateTy;
- typedef GRStmtNodeBuilder<GRConstants> StmtNodeBuilder;
- typedef GRBranchNodeBuilder<GRConstants> BranchNodeBuilder;
- typedef GRIndirectGotoNodeBuilder<GRConstants> IndirectGotoNodeBuilder;
- typedef ExplodedGraph<GRConstants> GraphTy;
+ typedef GRStmtNodeBuilder<GRExprEngine> StmtNodeBuilder;
+ typedef GRBranchNodeBuilder<GRExprEngine> BranchNodeBuilder;
+ typedef GRIndirectGotoNodeBuilder<GRExprEngine> IndirectGotoNodeBuilder;
+ typedef ExplodedGraph<GRExprEngine> GraphTy;
typedef GraphTy::NodeTy NodeTy;
class NodeSet {
bool StateCleaned;
public:
- GRConstants(GraphTy& g) : G(g), Liveness(G.getCFG(), G.getFunctionDecl()),
+ GRExprEngine(GraphTy& g) : G(g), Liveness(G.getCFG(), G.getFunctionDecl()),
Builder(NULL),
StateMgr(G.getContext(), G.getAllocator()),
ValMgr(StateMgr.getValueManager()),
null_iterator null_begin() { return ExplicitNullDeref.begin(); }
null_iterator null_end() { return ExplicitNullDeref.end(); }
- /// ProcessStmt - Called by GREngine. Used to generate new successor
+ /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
void ProcessStmt(Stmt* S, StmtNodeBuilder& builder);
- /// ProcessBranch - Called by GREngine. Used to generate successor
+ /// ProcessBranch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
void ProcessBranch(Expr* Condition, Stmt* Term, BranchNodeBuilder& builder);
- /// ProcessIndirectGoto - Called by GREngine. Used to generate successor
+ /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
void ProcessIndirectGoto(IndirectGotoNodeBuilder& builder);
} // end anonymous namespace
-GRConstants::StateTy
-GRConstants::SetValue(StateTy St, Expr* S, const RValue& V) {
+GRExprEngine::StateTy
+GRExprEngine::SetValue(StateTy St, Expr* S, const RValue& V) {
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
return StateMgr.SetValue(St, S, isBlkExpr, V);
}
-const GRConstants::StateTy::BufferTy&
-GRConstants::SetValue(StateTy St, Expr* S, const RValue::BufferTy& RB,
+const GRExprEngine::StateTy::BufferTy&
+GRExprEngine::SetValue(StateTy St, Expr* S, const RValue::BufferTy& RB,
StateTy::BufferTy& RetBuf) {
assert (RetBuf.empty());
return RetBuf;
}
-GRConstants::StateTy
-GRConstants::SetValue(StateTy St, const LValue& LV, const RValue& V) {
+GRExprEngine::StateTy
+GRExprEngine::SetValue(StateTy St, const LValue& LV, const RValue& V) {
if (LV.isUnknown())
return St;
return StateMgr.SetValue(St, LV, V);
}
-void GRConstants::ProcessBranch(Expr* Condition, Stmt* Term,
+void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term,
BranchNodeBuilder& builder) {
// Remove old bindings for subexpressions.
builder.markInfeasible(false);
}
-/// ProcessIndirectGoto - Called by GREngine. Used to generate successor
+/// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
-void GRConstants::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {
+void GRExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {
StateTy St = builder.getState();
LValue V = cast<LValue>(GetValue(St, builder.getTarget()));
builder.generateNode(I, St);
}
-void GRConstants::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
+void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
NodeSet& Dst) {
bool hasR2;
-void GRConstants::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
+void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
Builder = &builder;
StmtEntryNode = builder.getLastNode();
Builder = NULL;
}
-GRConstants::NodeTy*
-GRConstants::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St) {
+GRExprEngine::NodeTy*
+GRExprEngine::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St) {
// If the state hasn't changed, don't generate a new node.
if (St == Pred->getState())
return N;
}
-void GRConstants::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred,
+void GRExprEngine::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred,
const StateTy::BufferTy& SB) {
for (StateTy::BufferTy::const_iterator I=SB.begin(), E=SB.end(); I!=E; ++I)
Nodify(Dst, S, Pred, *I);
}
-void GRConstants::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst) {
+void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst) {
if (D != CurrentStmt) {
Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
return;
SetValue(St, D, GetValue(St, lval::DeclVal(D->getDecl()))));
}
-void GRConstants::VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst) {
+void GRExprEngine::VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst) {
QualType T = CastE->getType();
}
}
-void GRConstants::VisitDeclStmt(DeclStmt* DS, GRConstants::NodeTy* Pred,
- GRConstants::NodeSet& Dst) {
+void GRExprEngine::VisitDeclStmt(DeclStmt* DS, GRExprEngine::NodeTy* Pred,
+ GRExprEngine::NodeSet& Dst) {
StateTy St = Pred->getState();
}
-void GRConstants::VisitGuardedExpr(Expr* S, Expr* LHS, Expr* RHS,
+void GRExprEngine::VisitGuardedExpr(Expr* S, Expr* LHS, Expr* RHS,
NodeTy* Pred, NodeSet& Dst) {
StateTy St = Pred->getState();
}
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
-void GRConstants::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* S,
+void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* S,
NodeTy* Pred,
NodeSet& Dst) {
}
-void GRConstants::VisitUnaryOperator(UnaryOperator* U,
- GRConstants::NodeTy* Pred,
- GRConstants::NodeSet& Dst) {
+void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
+ GRExprEngine::NodeTy* Pred,
+ GRExprEngine::NodeSet& Dst) {
NodeSet S1;
UnaryOperator::Opcode Op = U->getOpcode();
}
}
-void GRConstants::VisitAssignmentLHS(Expr* E, GRConstants::NodeTy* Pred,
- GRConstants::NodeSet& Dst) {
+void GRExprEngine::VisitAssignmentLHS(Expr* E, GRExprEngine::NodeTy* Pred,
+ GRExprEngine::NodeSet& Dst) {
if (isa<DeclRefExpr>(E)) {
Dst.Add(Pred);
Visit(E, Pred, Dst);
}
-void GRConstants::VisitBinaryOperator(BinaryOperator* B,
- GRConstants::NodeTy* Pred,
- GRConstants::NodeSet& Dst) {
+void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
+ GRExprEngine::NodeTy* Pred,
+ GRExprEngine::NodeSet& Dst) {
NodeSet S1;
if (B->isAssignmentOp())
}
-void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
- GRConstants::NodeSet& Dst) {
+void GRExprEngine::Visit(Stmt* S, GRExprEngine::NodeTy* Pred,
+ GRExprEngine::NodeSet& Dst) {
// FIXME: add metadata to the CFG so that we can disable
// this check when we KNOW that there is no block-level subexpression.
// "Assume" logic.
//===----------------------------------------------------------------------===//
-GRConstants::StateTy GRConstants::Assume(StateTy St, LValue Cond,
+GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, LValue Cond,
bool Assumption,
bool& isFeasible) {
}
}
-GRConstants::StateTy GRConstants::Assume(StateTy St, NonLValue Cond,
+GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, NonLValue Cond,
bool Assumption,
bool& isFeasible) {
}
}
-GRConstants::StateTy
-GRConstants::AssumeSymNE(StateTy St, SymbolID sym,
+GRExprEngine::StateTy
+GRExprEngine::AssumeSymNE(StateTy St, SymbolID sym,
const llvm::APSInt& V, bool& isFeasible) {
// First, determine if sym == X, where X != V.
return StateMgr.AddNE(St, sym, V);
}
-GRConstants::StateTy
-GRConstants::AssumeSymEQ(StateTy St, SymbolID sym,
+GRExprEngine::StateTy
+GRExprEngine::AssumeSymEQ(StateTy St, SymbolID sym,
const llvm::APSInt& V, bool& isFeasible) {
// First, determine if sym == X, where X != V.
return StateMgr.AddEQ(St, sym, V);
}
-GRConstants::StateTy
-GRConstants::AssumeSymInt(StateTy St, bool Assumption,
+GRExprEngine::StateTy
+GRExprEngine::AssumeSymInt(StateTy St, bool Assumption,
const SymIntConstraint& C, bool& isFeasible) {
switch (C.getOpcode()) {
//===----------------------------------------------------------------------===//
#ifndef NDEBUG
-static GRConstants* GraphPrintCheckerState;
+static GRExprEngine* GraphPrintCheckerState;
namespace llvm {
template<>
-struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
+struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
public DefaultDOTGraphTraits {
- static void PrintVarBindings(std::ostream& Out, GRConstants::StateTy St) {
+ static void PrintVarBindings(std::ostream& Out, GRExprEngine::StateTy St) {
Out << "Variables:\\l";
bool isFirst = true;
- for (GRConstants::StateTy::vb_iterator I=St.vb_begin(),
+ for (GRExprEngine::StateTy::vb_iterator I=St.vb_begin(),
E=St.vb_end(); I!=E;++I) {
if (isFirst)
}
- static void PrintSubExprBindings(std::ostream& Out, GRConstants::StateTy St) {
+ static void PrintSubExprBindings(std::ostream& Out, GRExprEngine::StateTy St) {
bool isFirst = true;
- for (GRConstants::StateTy::seb_iterator I=St.seb_begin(), E=St.seb_end();
+ for (GRExprEngine::StateTy::seb_iterator I=St.seb_begin(), E=St.seb_end();
I != E;++I) {
if (isFirst) {
}
}
- static void PrintBlkExprBindings(std::ostream& Out, GRConstants::StateTy St) {
+ static void PrintBlkExprBindings(std::ostream& Out, GRExprEngine::StateTy St) {
bool isFirst = true;
- for (GRConstants::StateTy::beb_iterator I=St.beb_begin(), E=St.beb_end();
+ for (GRExprEngine::StateTy::beb_iterator I=St.beb_begin(), E=St.beb_end();
I != E; ++I) {
if (isFirst) {
Out << "\\l\\lBlock-level Expressions:\\l";
}
}
- static void PrintEQ(std::ostream& Out, GRConstants::StateTy St) {
+ static void PrintEQ(std::ostream& Out, GRExprEngine::StateTy St) {
ValueState::ConstantEqTy CE = St.getImpl()->ConstantEq;
if (CE.isEmpty())
Out << "\\l $" << I.getKey() << " : " << I.getData()->toString();
}
- static void PrintNE(std::ostream& Out, GRConstants::StateTy St) {
+ static void PrintNE(std::ostream& Out, GRExprEngine::StateTy St) {
ValueState::ConstantNotEqTy NE = St.getImpl()->ConstantNotEq;
if (NE.isEmpty())
}
}
- static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
+ static std::string getNodeLabel(const GRExprEngine::NodeTy* N, void*) {
std::ostringstream Out;
// Program Location.
#endif
namespace clang {
-void RunGRConstants(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
+void RunGRExprEngine(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
Diagnostic& Diag) {
- GREngine<GRConstants> Engine(cfg, FD, Ctx);
+ GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
Engine.ExecuteWorkList();
// Look for explicit-Null dereferences and warn about them.
- GRConstants* CheckerState = &Engine.getCheckerState();
+ GRExprEngine* CheckerState = &Engine.getCheckerState();
- for (GRConstants::null_iterator I=CheckerState->null_begin(),
+ for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
E=CheckerState->null_end(); I!=E; ++I) {
const PostStmt& L = cast<PostStmt>((*I)->getLocation());
#ifndef NDEBUG
GraphPrintCheckerState = CheckerState;
- llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
+ llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRExprEngine");
GraphPrintCheckerState = NULL;
#endif
}
-//==- GREngine.cpp - Path-Sensitive Dataflow Engine ----------------*- C++ -*-//
+//==- GRCoreEngine.cpp - Path-Sensitive Dataflow Engine ----------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/PathSensitive/GREngine.h"
+#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
#include "clang/AST/Expr.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Casting.h"
GRWorkList* GRWorkList::MakeDFS() { return new DFS(); }
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
-bool GREngineImpl::ExecuteWorkList(unsigned Steps) {
+bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
if (G->num_roots() == 0) { // Initialize the analysis by constructing
// the root if none exists.
return WList->hasWork();
}
-void GREngineImpl::HandleBlockEdge(const BlockEdge& L, ExplodedNodeImpl* Pred) {
+void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L, ExplodedNodeImpl* Pred) {
CFGBlock* Blk = L.getDst();
GenerateNode(BlockEntrance(Blk), Pred->State, Pred);
}
-void GREngineImpl::HandleBlockEntrance(const BlockEntrance& L,
+void GRCoreEngineImpl::HandleBlockEntrance(const BlockEntrance& L,
ExplodedNodeImpl* Pred) {
// Increment the block counter.
}
-void GREngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNodeImpl* Pred) {
+void GRCoreEngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNodeImpl* Pred) {
if (Stmt* Term = B->getTerminator()) {
switch (Term->getStmtClass()) {
GenerateNode(BlockEdge(getCFG(),B,*(B->succ_begin())), Pred->State, Pred);
}
-void GREngineImpl::HandleBranch(Expr* Cond, Stmt* Term, CFGBlock * B,
+void GRCoreEngineImpl::HandleBranch(Expr* Cond, Stmt* Term, CFGBlock * B,
ExplodedNodeImpl* Pred) {
assert (B->succ_size() == 2);
ProcessBranch(Cond, Term, Builder);
}
-void GREngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B,
+void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B,
unsigned StmtIdx, ExplodedNodeImpl* Pred) {
assert (!B->empty());
/// GenerateNode - Utility method to generate nodes, hook up successors,
/// and add nodes to the worklist.
-void GREngineImpl::GenerateNode(const ProgramPoint& Loc, void* State,
+void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc, void* State,
ExplodedNodeImpl* Pred) {
bool IsNew;
}
GRStmtNodeBuilderImpl::GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
- ExplodedNodeImpl* N, GREngineImpl* e)
+ ExplodedNodeImpl* N, GRCoreEngineImpl* e)
: Eng(*e), B(*b), Idx(idx), LastNode(N), Populated(false) {
Deferred.insert(N);
}
-//==- GREngine.h - Path-Sensitive Dataflow Engine ------------------*- C++ -*-//
+//==- GRCoreEngine.h - Path-Sensitive Dataflow Engine ------------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
class LabelStmt;
//===----------------------------------------------------------------------===//
-/// GREngineImpl - Implements the core logic of the graph-reachability analysis.
+/// GRCoreEngineImpl - Implements the core logic of the graph-reachability analysis.
/// It traverses the CFG and generates the ExplodedGraph. Program "states"
-/// are treated as opaque void pointers. The template class GREngine
-/// (which subclasses GREngineImpl) provides the matching component
+/// are treated as opaque void pointers. The template class GRCoreEngine
+/// (which subclasses GRCoreEngineImpl) provides the matching component
/// to the engine that knows the actual types for states. Note that this
/// engine only dispatches to transfer functions as the statement and
/// block-level. The analyses themselves must implement any transfer
/// function logic and the sub-expression level (if any).
-class GREngineImpl {
+class GRCoreEngineImpl {
protected:
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
/// getInitialState - Gets the void* representing the initial 'state'
/// of the analysis. This is simply a wrapper (implemented
- /// in GREngine) that performs type erasure on the initial
+ /// in GRCoreEngine) that performs type erasure on the initial
/// state returned by the checker object.
virtual void* getInitialState() = 0;
virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0;
private:
- GREngineImpl(const GREngineImpl&); // Do not implement.
- GREngineImpl& operator=(const GREngineImpl&);
+ GRCoreEngineImpl(const GRCoreEngineImpl&); // Do not implement.
+ GRCoreEngineImpl& operator=(const GRCoreEngineImpl&);
protected:
- GREngineImpl(ExplodedGraphImpl* g, GRWorkList* wl)
+ GRCoreEngineImpl(ExplodedGraphImpl* g, GRWorkList* wl)
: G(g), WList(wl), BCounterFactory(g->getAllocator()) {}
public:
/// steps. Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(unsigned Steps = 1000000);
- virtual ~GREngineImpl() {}
+ virtual ~GRCoreEngineImpl() {}
CFG& getCFG() { return G->getCFG(); }
};
class GRStmtNodeBuilderImpl {
- GREngineImpl& Eng;
+ GRCoreEngineImpl& Eng;
CFGBlock& B;
const unsigned Idx;
ExplodedNodeImpl* LastNode;
public:
GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
- ExplodedNodeImpl* N, GREngineImpl* e);
+ ExplodedNodeImpl* N, GRCoreEngineImpl* e);
~GRStmtNodeBuilderImpl();
};
class GRBranchNodeBuilderImpl {
- GREngineImpl& Eng;
+ GRCoreEngineImpl& Eng;
CFGBlock* Src;
CFGBlock* DstT;
CFGBlock* DstF;
public:
GRBranchNodeBuilderImpl(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF,
- ExplodedNodeImpl* pred, GREngineImpl* e)
+ ExplodedNodeImpl* pred, GRCoreEngineImpl* e)
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
GeneratedTrue(false), GeneratedFalse(false) {}
};
class GRIndirectGotoNodeBuilderImpl {
- GREngineImpl& Eng;
+ GRCoreEngineImpl& Eng;
CFGBlock* Src;
CFGBlock& DispatchBlock;
Expr* E;
public:
GRIndirectGotoNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
Expr* e, CFGBlock* dispatch,
- GREngineImpl* eng)
+ GRCoreEngineImpl* eng)
: Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
template<typename CHECKER>
-class GREngine : public GREngineImpl {
+class GRCoreEngine : public GRCoreEngineImpl {
public:
typedef CHECKER CheckerTy;
typedef typename CheckerTy::StateTy StateTy;
}
public:
- /// Construct a GREngine object to analyze the provided CFG using
+ /// Construct a GRCoreEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
- GREngine(CFG& cfg, FunctionDecl& fd, ASTContext& ctx)
- : GREngineImpl(new GraphTy(cfg, fd, ctx), GRWorkList::MakeDFS()),
+ GRCoreEngine(CFG& cfg, FunctionDecl& fd, ASTContext& ctx)
+ : GRCoreEngineImpl(new GraphTy(cfg, fd, ctx), GRWorkList::MakeDFS()),
Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {}
- /// Construct a GREngine object to analyze the provided CFG and to
+ /// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
- /// The GREngine object assumes ownership of 'wlist'.
- GREngine(CFG& cfg, FunctionDecl& fd, ASTContext& ctx, GRWorkList* wlist)
- : GREngineImpl(new GraphTy(cfg, fd, ctx), wlist),
+ /// The GRCoreEngine object assumes ownership of 'wlist'.
+ GRCoreEngine(CFG& cfg, FunctionDecl& fd, ASTContext& ctx, GRWorkList* wlist)
+ : GRCoreEngineImpl(new GraphTy(cfg, fd, ctx), wlist),
Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {}
- virtual ~GREngine() {}
+ virtual ~GRCoreEngine() {}
/// getGraph - Returns the exploded graph.
GraphTy& getGraph() {