From: Ted Kremenek Date: Wed, 9 Jan 2008 22:49:37 +0000 (+0000) Subject: Removed some files related to the path-sensitive solver as part of some X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2f4ef2c11c5cd8dcd5aa3d691f3a4bd971f96c2;p=clang Removed some files related to the path-sensitive solver as part of some code restructuring. (new files will be introduced shortly) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45785 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRConstantPropagation.cpp b/Analysis/GRConstantPropagation.cpp deleted file mode 100644 index 8bc0b3b89e..0000000000 --- a/Analysis/GRConstantPropagation.cpp +++ /dev/null @@ -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(v) | VTString) {} - - ConstV(const ObjCStringLiteral* v) - : Data(reinterpret_cast(v) | VTObjCString) {} - - ConstV(llvm::APInt* v) - : Data(reinterpret_cast(v) | VTInt) {} - - ConstV(llvm::APFloat* v) - : Data(reinterpret_cast(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(const ConstV& V) {\ - return V.getVT() == FLAG;\ -}\ -\ -template <> struct cast_retty_impl {\ - 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 { - typedef void* SimpleType; - static SimpleType getSimplifiedValue(const ConstV &Val) { - return Val.getData(); - } -}; - -} // end llvm namespace - - diff --git a/Analysis/ReachabilityEngine.cpp b/Analysis/ReachabilityEngine.cpp deleted file mode 100644 index 679be51351..0000000000 --- a/Analysis/ReachabilityEngine.cpp +++ /dev/null @@ -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(Loc)) { - Stmt* S = cast(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(V->getLocation()),V); - break; - - case ProgramEdge::BlkStmt: - ProcessBlkStmt(cast(V->getLocation()),V); - break; - - case ProgramEdge::StmtBlk: - ProcessStmtBlk(cast(V->getLocation()),V); - break; - - case ProgramEdge::StmtStmt: - ProcessStmt(cast(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); - } -} diff --git a/include/clang/Analysis/PathSensitive/ReachabilityEngine.h b/include/clang/Analysis/PathSensitive/ReachabilityEngine.h deleted file mode 100644 index d4b5f38da9..0000000000 --- a/include/clang/Analysis/PathSensitive/ReachabilityEngine.h +++ /dev/null @@ -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 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 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 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 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 -class ReachabilityEngine : public ReachabilityEngineImpl { -public: - typedef CHECKER CheckerTy; - typedef typename CheckerTy::StateTy StateTy; - typedef ExplodedGraph 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(G.get()); } - - /// getCheckerState - Returns the internal checker state. - CheckerTy& getCheckerState() { - return *static_cast(G.get())->getCheckerState(); - } - - /// takeGraph - Returns the exploded graph. Ownership of the graph is - /// transfered to the caller. - GraphTy* takeGraph() { return static_cast(G.take()); } -}; - -} // end clang namespace - -#endif