clang API Documentation

PostOrderCFGView.h
Go to the documentation of this file.
00001 //===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements post order view of the blocks in a CFG.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
00015 #define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
00016 
00017 #include <vector>
00018 //#include <algorithm>
00019 
00020 #include "llvm/ADT/PostOrderIterator.h"
00021 #include "llvm/ADT/DenseMap.h"
00022 #include "llvm/ADT/BitVector.h"
00023 
00024 #include "clang/Analysis/AnalysisContext.h"
00025 #include "clang/Analysis/CFG.h"
00026 
00027 namespace clang {
00028 
00029 class PostOrderCFGView : public ManagedAnalysis {
00030   virtual void anchor();
00031 public:
00032   /// \brief Implements a set of CFGBlocks using a BitVector.
00033   ///
00034   /// This class contains a minimal interface, primarily dictated by the SetType
00035   /// template parameter of the llvm::po_iterator template, as used with
00036   /// external storage. We also use this set to keep track of which CFGBlocks we
00037   /// visit during the analysis.
00038   class CFGBlockSet {
00039     llvm::BitVector VisitedBlockIDs;
00040   public:
00041     // po_iterator requires this iterator, but the only interface needed is the
00042     // value_type typedef.
00043     struct iterator { typedef const CFGBlock *value_type; };
00044 
00045     CFGBlockSet() {}
00046     CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
00047 
00048     /// \brief Set the bit associated with a particular CFGBlock.
00049     /// This is the important method for the SetType template parameter.
00050     bool insert(const CFGBlock *Block) {
00051       // Note that insert() is called by po_iterator, which doesn't check to
00052       // make sure that Block is non-null.  Moreover, the CFGBlock iterator will
00053       // occasionally hand out null pointers for pruned edges, so we catch those
00054       // here.
00055       if (!Block)
00056         return false;  // if an edge is trivially false.
00057       if (VisitedBlockIDs.test(Block->getBlockID()))
00058         return false;
00059       VisitedBlockIDs.set(Block->getBlockID());
00060       return true;
00061     }
00062 
00063     /// \brief Check if the bit for a CFGBlock has been already set.
00064     /// This method is for tracking visited blocks in the main threadsafety
00065     /// loop. Block must not be null.
00066     bool alreadySet(const CFGBlock *Block) {
00067       return VisitedBlockIDs.test(Block->getBlockID());
00068     }
00069   };
00070 
00071 private:
00072   typedef llvm::po_iterator<const CFG*, CFGBlockSet, true>  po_iterator;
00073   std::vector<const CFGBlock*> Blocks;
00074 
00075   typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy;
00076   BlockOrderTy BlockOrder;
00077 
00078 public:
00079   typedef std::vector<const CFGBlock *>::reverse_iterator iterator;
00080   typedef std::vector<const CFGBlock *>::const_reverse_iterator const_iterator;
00081 
00082   PostOrderCFGView(const CFG *cfg);
00083 
00084   iterator begin() { return Blocks.rbegin(); }
00085   iterator end()   { return Blocks.rend(); }
00086 
00087   const_iterator begin() const { return Blocks.rbegin(); }
00088   const_iterator end() const { return Blocks.rend(); }
00089 
00090   bool empty() const { return begin() == end(); }
00091 
00092   struct BlockOrderCompare;
00093   friend struct BlockOrderCompare;
00094 
00095   struct BlockOrderCompare {
00096     const PostOrderCFGView &POV;
00097   public:
00098     BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {}
00099     bool operator()(const CFGBlock *b1, const CFGBlock *b2) const;
00100   };
00101 
00102   BlockOrderCompare getComparator() const {
00103     return BlockOrderCompare(*this);
00104   }
00105 
00106   // Used by AnalyisContext to construct this object.
00107   static const void *getTag();
00108 
00109   static PostOrderCFGView *create(AnalysisDeclContext &analysisContext);
00110 };
00111 
00112 } // end clang namespace
00113 
00114 #endif
00115