text: // BlkExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- C++ --*--
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  //
  // This file provides definition of dataflow types used by analyses such
  // as LiveVariables and UninitializedValues.  The underlying dataflow values
  // are implemented as bitvectors, but the definitions in this file include
  // the necessary boilerplate to use with our dataflow framework.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef LLVM_CLANG_STMTDECLBVDVAL_H
  #define LLVM_CLANG_STMTDECLBVDVAL_H
  
  #include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion
  #include "clang/Analysis/CFG.h"
  #include "llvm/ADT/BitVector.h"
  #include "llvm/ADT/DenseMap.h"
  
  namespace clang {
  
    class Stmt;
    class ASTContext;
  
  struct DeclBitVector_Types {
  
    class Idx {
      unsigned I;
    public:
      explicit Idx(unsigned i) : I(i) {}
      Idx() : I(~0U) {}
  
      bool isValid() const {
        return I != ~0U;
      }
      operator unsigned() const {
        assert (isValid());
        return I;
      }
    };
  
    //===--------------------------------------------------------------------===//
    // AnalysisDataTy - Whole-function meta data.
    //===--------------------------------------------------------------------===//
  
    class AnalysisDataTy {
    public:
      typedef llvm::DenseMap<const NamedDecl*, unsigned > DMapTy;
      typedef DMapTy::const_iterator decl_iterator;
  
    protected:
      DMapTy DMap;
      unsigned NDecls;
  
    public:
  
      AnalysisDataTy() : NDecls(0) {}
      virtual ~AnalysisDataTy() {}
  
      bool isTracked(const NamedDecl *SD) { return DMap.find(SD) != DMap.end(); }
  
      Idx getIdx(const NamedDecl *SD) const {
        DMapTy::const_iterator I = DMap.find(SD);
        return I == DMap.end() ? Idx() : Idx(I->second);
      }
  
      unsigned getNumDecls() const { return NDecls; }
  
      void Register(const NamedDecl *SD) {
        if (!isTracked(SD)) DMap[SD] = NDecls++;
      }
  
      decl_iterator begin_decl() const { return DMap.begin(); }
      decl_iterator end_decl() const { return DMap.end(); }
    };
  
    //===--------------------------------------------------------------------===//
    // ValTy - Dataflow value.
    //===--------------------------------------------------------------------===//
  
    class ValTy {
      llvm::BitVector DeclBV;
    public:
  
      void resetDeclValues(AnalysisDataTy& AD) {
        DeclBV.resize(AD.getNumDecls());
        DeclBV.reset();
      }
  
      void setDeclValues(AnalysisDataTy& AD) {
        DeclBV.resize(AD.getNumDecls());
        DeclBV.set();
      }
  
      void resetValues(AnalysisDataTy& AD) {
        resetDeclValues(AD);
      }
  
      bool operator==(const ValTy& RHS) const {
        assert (sizesEqual(RHS));
        return DeclBV == RHS.DeclBV;
      }
  
      void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; }
  
      llvm::BitVector::reference getBit(unsigned i) {
        return DeclBV[i];
      }
  
      bool getBit(unsigned i) const {
        return DeclBV[i];
      }
  
      llvm::BitVector::reference
      operator()(const NamedDecl *ND, const AnalysisDataTy& AD) {
        return getBit(AD.getIdx(ND));
      }
  
      bool operator()(const NamedDecl *ND, const AnalysisDataTy& AD) const {
        return getBit(AD.getIdx(ND));
      }
  
      llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; }
      const llvm::BitVector::reference getDeclBit(unsigned i) const {
        return const_cast<llvm::BitVector&>(DeclBV)[i];
      }
  
      ValTy& operator|=(const ValTy& RHS) {
        assert (sizesEqual(RHS));
        DeclBV |= RHS.DeclBV;
        return *this;
      }
  
      ValTy& operator&=(const ValTy& RHS) {
        assert (sizesEqual(RHS));
        DeclBV &= RHS.DeclBV;
        return *this;
      }
  
      ValTy& OrDeclBits(const ValTy& RHS) {
        return operator|=(RHS);
      }
  
      ValTy& AndDeclBits(const ValTy& RHS) {
        return operator&=(RHS);
      }
  
      bool sizesEqual(const ValTy& RHS) const {
        return DeclBV.size() == RHS.DeclBV.size();
      }
    };
  
    //===--------------------------------------------------------------------===//
    // Some useful merge operations.
    //===--------------------------------------------------------------------===//
  
    struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
    struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
  };
  
  
  struct StmtDeclBitVector_Types {
  
    //===--------------------------------------------------------------------===//
    // AnalysisDataTy - Whole-function meta data.
    //===--------------------------------------------------------------------===//
  
    class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy {
      ASTContext *ctx;
      CFG* cfg;
    public:
      AnalysisDataTy() : ctx(0), cfg(0) {}
      virtual ~AnalysisDataTy() {}
  
      void setContext(ASTContext &c) { ctx = &c; }
      ASTContext &getContext() {
        assert(ctx && "ASTContext should not be NULL.");
        return *ctx;
      }
  
      void setCFG(CFG& c) { cfg = &c; }
      CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
  
      bool isTracked(const Stmt *S) { return cfg->isBlkExpr(S); }
      using DeclBitVector_Types::AnalysisDataTy::isTracked;
  
      unsigned getIdx(const Stmt *S) const {
        CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
        assert(I && "Stmtession not tracked for bitvector.");
        return I;
      }
      using DeclBitVector_Types::AnalysisDataTy::getIdx;
  
      unsigned getNumBlkExprs() const { return cfg->getNumBlkExprs(); }
    };
  
    //===--------------------------------------------------------------------===//
    // ValTy - Dataflow value.
    //===--------------------------------------------------------------------===//
  
    class ValTy : public DeclBitVector_Types::ValTy {
      llvm::BitVector BlkExprBV;
      typedef DeclBitVector_Types::ValTy ParentTy;
  
      static inline ParentTy& ParentRef(ValTy& X) {
        return static_cast<ParentTy&>(X);
      }
  
      static inline const ParentTy& ParentRef(const ValTy& X) {
        return static_cast<const ParentTy&>(X);
      }
  
    public:
  
      void resetBlkExprValues(AnalysisDataTy& AD) {
        BlkExprBV.resize(AD.getNumBlkExprs());
        BlkExprBV.reset();
      }
  
      void setBlkExprValues(AnalysisDataTy& AD) {
        BlkExprBV.resize(AD.getNumBlkExprs());
        BlkExprBV.set();
      }
  
      void resetValues(AnalysisDataTy& AD) {
        resetDeclValues(AD);
        resetBlkExprValues(AD);
      }
  
      void setValues(AnalysisDataTy& AD) {
        setDeclValues(AD);
        setBlkExprValues(AD);
      }
  
      bool operator==(const ValTy& RHS) const {
        return ParentRef(*this) == ParentRef(RHS)
            && BlkExprBV == RHS.BlkExprBV;
      }
  
      void copyValues(const ValTy& RHS) {
        ParentRef(*this).copyValues(ParentRef(RHS));
        BlkExprBV = RHS.BlkExprBV;
      }
  
      llvm::BitVector::reference
      operator()(const Stmt *S, const AnalysisDataTy& AD) {
        return BlkExprBV[AD.getIdx(S)];
      }
      const llvm::BitVector::reference
      operator()(const Stmt *S, const AnalysisDataTy& AD) const {
        return const_cast<ValTy&>(*this)(S,AD);
      }
  
      using DeclBitVector_Types::ValTy::operator();
  
  
      llvm::BitVector::reference getStmtBit(unsigned i) { return BlkExprBV[i]; }
      const llvm::BitVector::reference getStmtBit(unsigned i) const {
        return const_cast<llvm::BitVector&>(BlkExprBV)[i];
      }
  
      ValTy& OrBlkExprBits(const ValTy& RHS) {
        BlkExprBV |= RHS.BlkExprBV;
        return *this;
      }
  
      ValTy& AndBlkExprBits(const ValTy& RHS) {
        BlkExprBV &= RHS.BlkExprBV;
        return *this;
      }
  
      ValTy& operator|=(const ValTy& RHS) {
        assert (sizesEqual(RHS));
        ParentRef(*this) |= ParentRef(RHS);
        BlkExprBV |= RHS.BlkExprBV;
        return *this;
      }
  
      ValTy& operator&=(const ValTy& RHS) {
        assert (sizesEqual(RHS));
        ParentRef(*this) &= ParentRef(RHS);
        BlkExprBV &= RHS.BlkExprBV;
        return *this;
      }
  
      bool sizesEqual(const ValTy& RHS) const {
        return ParentRef(*this).sizesEqual(ParentRef(RHS))
            && BlkExprBV.size() == RHS.BlkExprBV.size();
      }
    };
  
    //===--------------------------------------------------------------------===//
    // Some useful merge operations.
    //===--------------------------------------------------------------------===//
  
    struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
    struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
  
  };
  } // end namespace clang
  
  #endif
  