Removed some files related to the path-sensitive solver as part of some

code restructuring.  (new files will be introduced shortly)

llvm-svn: 45785
This commit is contained in:
Ted Kremenek 2008-01-09 22:49:37 +00:00
parent c6edcbdb5d
commit fed4cce0cc
3 changed files with 0 additions and 455 deletions

View File

@ -1,96 +0,0 @@
//===-- GRConstantPropagation.cpp --------------------------------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Constant Propagation via Graph Reachability
//
// This files defines a simple analysis that performs path-sensitive
// constant propagation within a function. An example use of this analysis
// is to perform simple checks for NULL dereferences.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "clang/AST/Expr.h"
#include "clang/AST/CFG.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/ImmutableMap.h"
using namespace clang;
using llvm::APInt;
using llvm::APFloat;
using llvm::dyn_cast;
using llvm::cast;
//===----------------------------------------------------------------------===//
// ConstV - Represents a variant over APInt, APFloat, and const char
//===----------------------------------------------------------------------===//
namespace {
class ConstV {
uintptr_t Data;
public:
enum VariantType { VTString = 0x0, VTObjCString = 0x1,
VTFloat = 0x2, VTInt = 0x3,
Flags = 0x3 };
ConstV(const StringLiteral* v)
: Data(reinterpret_cast<uintptr_t>(v) | VTString) {}
ConstV(const ObjCStringLiteral* v)
: Data(reinterpret_cast<uintptr_t>(v) | VTObjCString) {}
ConstV(llvm::APInt* v)
: Data(reinterpret_cast<uintptr_t>(v) | VTInt) {}
ConstV(llvm::APFloat* v)
: Data(reinterpret_cast<uintptr_t>(v) | VTFloat) {}
inline void* getData() const { return (void*) (Data & ~Flags); }
inline VariantType getVT() const { return (VariantType) (Data & Flags); }
inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddPointer(getData());
}
};
} // end anonymous namespace
// Overload machinery for casting from ConstV to contained classes.
namespace llvm {
#define CV_OBJ_CAST(CLASS,FLAG)\
template<> inline bool isa<CLASS,ConstV>(const ConstV& V) {\
return V.getVT() == FLAG;\
}\
\
template <> struct cast_retty_impl<CLASS, ConstV> {\
typedef const CLASS* ret_type;\
};
CV_OBJ_CAST(APInt,ConstV::VTInt)
CV_OBJ_CAST(APFloat,ConstV::VTFloat)
CV_OBJ_CAST(StringLiteral,ConstV::VTString)
CV_OBJ_CAST(ObjCStringLiteral,ConstV::VTObjCString)
#undef CV_OBJ_CAST
template <> struct simplify_type<ConstV> {
typedef void* SimpleType;
static SimpleType getSimplifiedValue(const ConstV &Val) {
return Val.getData();
}
};
} // end llvm namespace

View File

@ -1,177 +0,0 @@
//= ReachabilityEngine.cpp - Path-Sens. Dataflow Engine ------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a generic engine for intraprocedural, path-sensitive,
// dataflow analysis via graph reachability engine.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/ReachabilityEngine.h"
#include "clang/AST/Stmt.h"
#include "llvm/Support/Casting.h"
using namespace clang;
using clang::reng::WorkList;
using llvm::isa;
using llvm::cast;
// Place dstor here so that all of the virtual functions in DFS have their
// code placed in the object file of this translation unit.
clang::reng::DFS::~DFS() {}
ReachabilityEngineImpl::ReachabilityEngineImpl(CFG& c,
clang::reng::WorkList* wlist)
: cfg(c), WList(wlist) {}
ExplodedNodeImpl* ReachabilityEngineImpl::getNode(const ProgramEdge& Loc,
void* State,
ExplodedNodeImpl* Pred) {
bool IsNew;
ExplodedNodeImpl* V = G->getNodeImpl(Loc,State,&IsNew);
// Link the node with its predecessor.
V->addUntypedPredecessor(Pred);
if (IsNew) {
// Only add the node to the worklist if it was freshly generated.
WList->Enqueue(V);
// Check if the node's edge is a StmtStmtEdge where the destination
// statement is not a BlockLevelExpr. In this case, we must lazily
// populate ParentMap.
if (isa<StmtStmtEdge>(Loc)) {
Stmt* S = cast<StmtStmtEdge>(Loc).Dst();
assert (CurrentBlkExpr != NULL);
if (S != CurrentBlkExpr && ParentMap.find(S) == ParentMap.end()) {
// Populate ParentMap starting from CurrentBlkExpr.
PopulateParentMap(CurrentBlkExpr);
assert (ParentMap.find(S) != ParentMap.end());
}
}
}
return V;
}
void ReachabilityEngineImpl::PopulateParentMap(Stmt* Parent) {
for (Stmt::child_iterator I=Parent->child_begin(),
E=Parent->child_end(); I!=E; ++I) {
assert (ParentMap.find(*I) == ParentMap.end());
ParentMap[*I] = Parent;
PopulateParentMap(*I);
}
}
bool ReachabilityEngineImpl::ExecuteWorkList(unsigned Steps) {
// Initialize the analysis by constructing the root if none exists.
if (G->num_roots() == 0) {
// Get the entry block. Make sure that it has 1 (and only 1) successor.
CFGBlock* Entry = &cfg.getEntry();
assert (Entry->empty() && "Entry block must be empty.");
assert (Entry->succ_size() == 1 && "Entry block must have 1 successor.");
// Get the first (and only) successor of Entry.
CFGBlock* Succ = *(Entry->succ_begin());
// Construct an edge representing the starting location in the function.
BlkBlkEdge StartLoc(Entry,Succ);
// Create the root node.
WList->Enqueue(G->addRoot(G->getNodeImpl(StartLoc,getInitialState(),NULL)));
}
while (Steps && WList->hasWork()) {
--Steps;
ExplodedNodeImpl* V = WList->Dequeue();
// Dispatch on the location type.
switch (V->getLocation().getKind()) {
case ProgramEdge::BlkBlk:
ProcessBlkBlk(cast<BlkBlkEdge>(V->getLocation()),V);
break;
case ProgramEdge::BlkStmt:
ProcessBlkStmt(cast<BlkStmtEdge>(V->getLocation()),V);
break;
case ProgramEdge::StmtBlk:
ProcessStmtBlk(cast<StmtBlkEdge>(V->getLocation()),V);
break;
case ProgramEdge::StmtStmt:
ProcessStmt(cast<StmtStmtEdge>(V->getLocation()).Dst(),V);
break;
default:
assert (false && "Unsupported edge type.");
}
}
return WList->hasWork();
}
void ReachabilityEngineImpl::ProcessBlkBlk(const BlkBlkEdge& E,
ExplodedNodeImpl* Pred) {
CFGBlock* Blk = E.Dst();
// Check if we are entering the EXIT block.
if (Blk == &cfg.getExit()) {
assert (cfg.getExit().size() == 0 && "EXIT block cannot contain Stmts.");
// Process the End-Of-Path.
void* State = ProcessEOP(Blk, Pred->State);
bool IsNew;
ExplodedNodeImpl* V = G->getNodeImpl(BlkStmtEdge(Blk,NULL),State,&IsNew);
V->addUntypedPredecessor(Pred);
if (IsNew) G->addEndOfPath(V);
return;
}
// FIXME: we will dispatch to a function that manipulates the state
// at the entrance to a block.
if (!Blk->empty()) {
// If 'Blk' has at least one statement, create a BlkStmtEdge and create
// the appropriate node. This is the common case.
getNode(BlkStmtEdge(Blk,Blk->front()), Pred->State, Pred);
}
else {
// Otherwise, create a node at the BlkStmtEdge right before the terminator
// (if any) is evaluated.
getNode(StmtBlkEdge(NULL,Blk),Pred->State, Pred);
}
}
void ReachabilityEngineImpl::ProcessBlkStmt(const BlkStmtEdge& E,
ExplodedNodeImpl* Pred) {
if (Stmt* S = E.Dst())
ProcessStmt(S,Pred);
else {
// No statement. Create an edge right before the terminator is evaluated.
getNode(StmtBlkEdge(NULL,E.Src()), Pred->State, Pred);
}
}
void ReachabilityEngineImpl::ProcessStmtBlk(const StmtBlkEdge& E,
ExplodedNodeImpl* Pred) {
CFGBlock* Blk = E.Dst();
if (Stmt* Terminator = Blk->getTerminator())
ProcessTerminator(Terminator,Pred);
else {
// No terminator. We should have only 1 successor.
assert (Blk->succ_size() == 1);
getNode(BlkBlkEdge(Blk,*(Blk->succ_begin())), Pred);
}
}

View File

@ -1,182 +0,0 @@
//==- ReachabilityEngine.h - Path-Sens. Dataflow Engine ------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a generic engine for intraprocedural, path-sensitive,
// dataflow analysis via graph reachability engine.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_REACHABILITYENGINE
#define LLVM_CLANG_ANALYSIS_REACHABILITYENGINE
#include "clang/AST/CFG.h"
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/OwningPtr.h"
namespace clang {
namespace reng {
class WorkList {
public:
virtual ~WorkList();
virtual bool hasWork() const = 0;
virtual void Enqueue(ExplodedNodeImpl* V) = 0;
virtual ExplodedNodeImpl* Dequeue() = 0;
};
class DFS : public WorkList {
llvm::SmallVector<ExplodedNodeImpl*,20> Stack;
public:
virtual ~DFS();
virtual bool hasWork() const {
return !Stack.empty();
}
virtual void Enqueue(ExplodedNodeImpl* V) {
Stack.push_back(V);
}
virtual ExplodedNodeImpl* Dequeue() {
ExplodedNodeImpl* V = Stack.back();
Stack.pop_back();
return V;
}
};
}
class ReachabilityEngineImpl {
protected:
typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
/// cfg - The control-flow graph of the function being analyzed.
CFG& cfg;
/// G - The simulation graph. Each node is a (location,state) pair.
llvm::OwningPtr<ExplodedGraphImpl> G;
/// ParentMap - A lazily populated map from a Stmt* to its parent Stmt*.
ParentMapTy ParentMap;
/// CurrentBlkExpr - The current Block-level expression being processed.
/// This is used when lazily populating ParentMap.
Stmt* CurrentBlkExpr;
/// WList - A set of queued nodes that need to be processed by the
/// worklist algorithm. It is up to the implementation of WList to decide
/// the order that nodes are processed.
llvm::OwningPtr<reng::WorkList> WList;
//==----------------------------------------------------------------------==//
// Internal methods.
/// getNode - Implemented by ReachabilityEngine<> subclass.
/// Creates/fetches a node and inserts it into the
ExplodedNodeImpl* getNode(const ProgramEdge& Loc, void* State,
ExplodedNodeImpl* Pred);
inline ExplodedNodeImpl* getNode(const ProgramEdge& Loc,
ExplodedNodeImpl* Pred) {
return getNode(Loc,Pred->State,Pred);
}
/// getInitialState - Gets the void* representing the initial 'state'
/// of the analysis. This is simply a wrapper (implemented
/// in ReachabilityEngine) that performs type erasure on the initial
/// state returned by the checker object.
virtual void* getInitialState() = 0;
/// PopulateParentMap - Populates ParentMap starting from the specified
/// expression.
void PopulateParentMap(Stmt* Parent);
void ProcessBlkBlk(const BlkBlkEdge& E, ExplodedNodeImpl* Pred);
void ProcessBlkStmt(const BlkStmtEdge& E, ExplodedNodeImpl* Pred);
void ProcessStmtBlk(const StmtBlkEdge& E, ExplodedNodeImpl* Pred);
virtual void* ProcessEOP(CFGBlock* Blk, void* State);
virtual void ProcessStmt(Stmt* S, ExplodedNodeImpl* Pred);
virtual void ProcessTerminator(Stmt* Terminator, ExplodedNodeImpl* Pred);
private:
ReachabilityEngineImpl(const ReachabilityEngineImpl&); // Do not implement.
ReachabilityEngineImpl& operator=(const ReachabilityEngineImpl&);
protected:
ReachabilityEngineImpl(CFG& c, reng::WorkList* wl);
public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(unsigned Steps = 1000000);
virtual ~ReachabilityEngineImpl() {}
};
template<typename CHECKER>
class ReachabilityEngine : public ReachabilityEngineImpl {
public:
typedef CHECKER CheckerTy;
typedef typename CheckerTy::StateTy StateTy;
typedef ExplodedGraph<CheckerTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
protected:
virtual void* getInitialState() {
return (void*) getCheckerState()->getInitialState();
}
virtual void* ProcessEOP(CFGBlock* Blk, void* State) {
// FIXME: Perform dispatch to adjust state.
return State;
}
virtual void ProcessStmt(Stmt* S, ExplodedNodeImpl* Pred) {
CurrentBlkExpr = S;
assert(false && "Not implemented.");
CurrentBlkExpr = NULL;
}
virtual void ProcessTerminator(Stmt* Terminator, ExplodedNodeImpl* Pred) {
assert(false && "Not implemented.");
}
public:
/// Construct a ReachabilityEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
ReachabilityEngine(CFG& Cfg)
: ReachabilityEngineImpl(cfg,new reng::DFS()) {}
/// Construct a ReachabilityEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
/// The ReachabilityEngine object assumes ownership of 'wlist'.
ReachabilityEngine(CFG& cfg, reng::WorkList* wlist)
: ReachabilityEngineImpl(cfg,wlist) {}
/// getGraph - Returns the exploded graph.
GraphTy& getGraph() { return *static_cast<GraphTy*>(G.get()); }
/// getCheckerState - Returns the internal checker state.
CheckerTy& getCheckerState() {
return *static_cast<GraphTy*>(G.get())->getCheckerState();
}
/// takeGraph - Returns the exploded graph. Ownership of the graph is
/// transfered to the caller.
GraphTy* takeGraph() { return static_cast<GraphTy*>(G.take()); }
};
} // end clang namespace
#endif