+++ /dev/null
-//===-- 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
-
-
+++ /dev/null
-//= 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);
- }
-}
+++ /dev/null
-//==- 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