//==- ProgramPoint.h - Program Points for Path-Sensitive 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 defines the interface ProgramPoint, which identifies a
//  distinct location in a function.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H

#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <string>
#include <utility>

namespace clang {

class AnalysisDeclContext;
class FunctionDecl;
class LocationContext;
class ProgramPointTag;
  
class ProgramPoint {
public:
  enum Kind { BlockEdgeKind,
              BlockEntranceKind,
              BlockExitKind,
              PreStmtKind,
              PreStmtPurgeDeadSymbolsKind,
              PostStmtPurgeDeadSymbolsKind,
              PostStmtKind,
              PreLoadKind,
              PostLoadKind,
              PreStoreKind,
              PostStoreKind,
              PostConditionKind,
              PostLValueKind,
              MinPostStmtKind = PostStmtKind,
              MaxPostStmtKind = PostLValueKind,
              PostInitializerKind,
              CallEnterKind,
              CallExitBeginKind,
              CallExitEndKind,
              PreImplicitCallKind,
              PostImplicitCallKind,
              MinImplicitCallKind = PreImplicitCallKind,
              MaxImplicitCallKind = PostImplicitCallKind,
              EpsilonKind};

private:
  const void *Data1;
  llvm::PointerIntPair<const void *, 2, unsigned> Data2;

  // The LocationContext could be NULL to allow ProgramPoint to be used in
  // context insensitive analysis.
  llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;

  llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;

protected:
  ProgramPoint() {}
  ProgramPoint(const void *P,
               Kind k,
               const LocationContext *l,
               const ProgramPointTag *tag = nullptr)
    : Data1(P),
      Data2(nullptr, (((unsigned) k) >> 0) & 0x3),
      L(l, (((unsigned) k) >> 2) & 0x3),
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
        assert(getKind() == k);
        assert(getLocationContext() == l);
        assert(getData1() == P);
      }
        
  ProgramPoint(const void *P1,
               const void *P2,
               Kind k,
               const LocationContext *l,
               const ProgramPointTag *tag = nullptr)
    : Data1(P1),
      Data2(P2, (((unsigned) k) >> 0) & 0x3),
      L(l, (((unsigned) k) >> 2) & 0x3),
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}

protected:
  const void *getData1() const { return Data1; }
  const void *getData2() const { return Data2.getPointer(); }
  void setData2(const void *d) { Data2.setPointer(d); }

public:
  /// Create a new ProgramPoint object that is the same as the original
  /// except for using the specified tag value.
  ProgramPoint withTag(const ProgramPointTag *tag) const {
    return ProgramPoint(getData1(), getData2(), getKind(),
                        getLocationContext(), tag);
  }

  /// \brief Convert to the specified ProgramPoint type, asserting that this
  /// ProgramPoint is of the desired type.
  template<typename T>
  T castAs() const {
    assert(T::isKind(*this));
    T t;
    ProgramPoint& PP = t;
    PP = *this;
    return t;
  }

  /// \brief Convert to the specified ProgramPoint type, returning None if this
  /// ProgramPoint is not of the desired type.
  template<typename T>
  Optional<T> getAs() const {
    if (!T::isKind(*this))
      return None;
    T t;
    ProgramPoint& PP = t;
    PP = *this;
    return t;
  }

  Kind getKind() const {
    unsigned x = Tag.getInt();
    x <<= 2;
    x |= L.getInt();
    x <<= 2;
    x |= Data2.getInt();
    return (Kind) x;
  }

  /// \brief Is this a program point corresponding to purge/removal of dead
  /// symbols and bindings.
  bool isPurgeKind() {
    Kind K = getKind();
    return (K == PostStmtPurgeDeadSymbolsKind ||
            K == PreStmtPurgeDeadSymbolsKind);
  }

  const ProgramPointTag *getTag() const { return Tag.getPointer(); }

  const LocationContext *getLocationContext() const {
    return L.getPointer();
  }

  // For use with DenseMap.  This hash is probably slow.
  unsigned getHashValue() const {
    llvm::FoldingSetNodeID ID;
    Profile(ID);
    return ID.ComputeHash();
  }

  bool operator==(const ProgramPoint & RHS) const {
    return Data1 == RHS.Data1 &&
           Data2 == RHS.Data2 &&
           L == RHS.L &&
           Tag == RHS.Tag;
  }

  bool operator!=(const ProgramPoint &RHS) const {
    return Data1 != RHS.Data1 ||
           Data2 != RHS.Data2 ||
           L != RHS.L ||
           Tag != RHS.Tag;
  }

  void Profile(llvm::FoldingSetNodeID& ID) const {
    ID.AddInteger((unsigned) getKind());
    ID.AddPointer(getData1());
    ID.AddPointer(getData2());
    ID.AddPointer(getLocationContext());
    ID.AddPointer(getTag());
  }

  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
                                      const LocationContext *LC,
                                      const ProgramPointTag *tag);
};

class BlockEntrance : public ProgramPoint {
public:
  BlockEntrance(const CFGBlock *B, const LocationContext *L,
                const ProgramPointTag *tag = nullptr)
    : ProgramPoint(B, BlockEntranceKind, L, tag) {    
    assert(B && "BlockEntrance requires non-null block");
  }

  const CFGBlock *getBlock() const {
    return reinterpret_cast<const CFGBlock*>(getData1());
  }

  Optional<CFGElement> getFirstElement() const {
    const CFGBlock *B = getBlock();
    return B->empty() ? Optional<CFGElement>() : B->front();
  }
  
private:
  friend class ProgramPoint;
  BlockEntrance() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == BlockEntranceKind;
  }
};

class BlockExit : public ProgramPoint {
public:
  BlockExit(const CFGBlock *B, const LocationContext *L)
    : ProgramPoint(B, BlockExitKind, L) {}

  const CFGBlock *getBlock() const {
    return reinterpret_cast<const CFGBlock*>(getData1());
  }

  const Stmt *getTerminator() const {
    return getBlock()->getTerminator();
  }

private:
  friend class ProgramPoint;
  BlockExit() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == BlockExitKind;
  }
};

class StmtPoint : public ProgramPoint {
public:
  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
            const ProgramPointTag *tag)
    : ProgramPoint(S, p2, k, L, tag) {
    assert(S);
  }

  const Stmt *getStmt() const { return (const Stmt*) getData1(); }

  template <typename T>
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }

protected:
  StmtPoint() {}
private:
  friend class ProgramPoint;
  static bool isKind(const ProgramPoint &Location) {
    unsigned k = Location.getKind();
    return k >= PreStmtKind && k <= MaxPostStmtKind;
  }
};


class PreStmt : public StmtPoint {
public:
  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
          const Stmt *SubStmt = nullptr)
    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}

  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }

private:
  friend class ProgramPoint;
  PreStmt() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PreStmtKind;
  }
};

class PostStmt : public StmtPoint {
protected:
  PostStmt() {}
  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
           const ProgramPointTag *tag = nullptr)
    : StmtPoint(S, data, k, L, tag) {}

public:
  explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
                    const ProgramPointTag *tag = nullptr)
    : StmtPoint(S, nullptr, k, L, tag) {}

  explicit PostStmt(const Stmt *S, const LocationContext *L,
                    const ProgramPointTag *tag = nullptr)
    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}

private:
  friend class ProgramPoint;
  static bool isKind(const ProgramPoint &Location) {
    unsigned k = Location.getKind();
    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
  }
};

// PostCondition represents the post program point of a branch condition.
class PostCondition : public PostStmt {
public:
  PostCondition(const Stmt *S, const LocationContext *L,
                const ProgramPointTag *tag = nullptr)
    : PostStmt(S, PostConditionKind, L, tag) {}

private:
  friend class ProgramPoint;
  PostCondition() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PostConditionKind;
  }
};

class LocationCheck : public StmtPoint {
protected:
  LocationCheck() {}
  LocationCheck(const Stmt *S, const LocationContext *L,
                ProgramPoint::Kind K, const ProgramPointTag *tag)
    : StmtPoint(S, nullptr, K, L, tag) {}
    
private:
  friend class ProgramPoint;
  static bool isKind(const ProgramPoint &location) {
    unsigned k = location.getKind();
    return k == PreLoadKind || k == PreStoreKind;
  }
};
  
class PreLoad : public LocationCheck {
public:
  PreLoad(const Stmt *S, const LocationContext *L,
          const ProgramPointTag *tag = nullptr)
    : LocationCheck(S, L, PreLoadKind, tag) {}
  
private:
  friend class ProgramPoint;
  PreLoad() {}
  static bool isKind(const ProgramPoint &location) {
    return location.getKind() == PreLoadKind;
  }
};

class PreStore : public LocationCheck {
public:
  PreStore(const Stmt *S, const LocationContext *L,
           const ProgramPointTag *tag = nullptr)
  : LocationCheck(S, L, PreStoreKind, tag) {}
  
private:
  friend class ProgramPoint;
  PreStore() {}
  static bool isKind(const ProgramPoint &location) {
    return location.getKind() == PreStoreKind;
  }
};

class PostLoad : public PostStmt {
public:
  PostLoad(const Stmt *S, const LocationContext *L,
           const ProgramPointTag *tag = nullptr)
    : PostStmt(S, PostLoadKind, L, tag) {}

private:
  friend class ProgramPoint;
  PostLoad() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PostLoadKind;
  }
};

/// \brief Represents a program point after a store evaluation.
class PostStore : public PostStmt {
public:
  /// Construct the post store point.
  /// \param Loc can be used to store the information about the location 
  /// used in the form it was uttered in the code.
  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
            const ProgramPointTag *tag = nullptr)
    : PostStmt(S, PostStoreKind, L, tag) {
    assert(getData2() == nullptr);
    setData2(Loc);
  }

  /// \brief Returns the information about the location used in the store,
  /// how it was uttered in the code.
  const void *getLocationValue() const {
    return getData2();
  }

private:
  friend class ProgramPoint;
  PostStore() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PostStoreKind;
  }
};

class PostLValue : public PostStmt {
public:
  PostLValue(const Stmt *S, const LocationContext *L,
             const ProgramPointTag *tag = nullptr)
    : PostStmt(S, PostLValueKind, L, tag) {}

private:
  friend class ProgramPoint;
  PostLValue() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PostLValueKind;
  }
};

/// Represents a point after we ran remove dead bindings BEFORE
/// processing the given statement.
class PreStmtPurgeDeadSymbols : public StmtPoint {
public:
  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
                       const ProgramPointTag *tag = nullptr)
    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }

private:
  friend class ProgramPoint;
  PreStmtPurgeDeadSymbols() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
  }
};

/// Represents a point after we ran remove dead bindings AFTER
/// processing the  given statement.
class PostStmtPurgeDeadSymbols : public StmtPoint {
public:
  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
                       const ProgramPointTag *tag = nullptr)
    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }

private:
  friend class ProgramPoint;
  PostStmtPurgeDeadSymbols() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
  }
};

class BlockEdge : public ProgramPoint {
public:
  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
    assert(B1 && "BlockEdge: source block must be non-null");
    assert(B2 && "BlockEdge: destination block must be non-null");    
  }

  const CFGBlock *getSrc() const {
    return static_cast<const CFGBlock*>(getData1());
  }

  const CFGBlock *getDst() const {
    return static_cast<const CFGBlock*>(getData2());
  }

private:
  friend class ProgramPoint;
  BlockEdge() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == BlockEdgeKind;
  }
};

class PostInitializer : public ProgramPoint {
public:
  /// \brief Construct a PostInitializer point that represents a location after
  ///   CXXCtorInitializer expression evaluation.
  ///
  /// \param I The initializer.
  /// \param Loc The location of the field being initialized.
  PostInitializer(const CXXCtorInitializer *I,
                  const void *Loc,
                  const LocationContext *L)
    : ProgramPoint(I, Loc, PostInitializerKind, L) {}

  const CXXCtorInitializer *getInitializer() const {
    return static_cast<const CXXCtorInitializer *>(getData1());
  }

  /// \brief Returns the location of the field.
  const void *getLocationValue() const {
    return getData2();
  }

private:
  friend class ProgramPoint;
  PostInitializer() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PostInitializerKind;
  }
};

/// Represents an implicit call event.
///
/// The nearest statement is provided for diagnostic purposes.
class ImplicitCallPoint : public ProgramPoint {
public:
  ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
                    const LocationContext *L, const ProgramPointTag *Tag)
    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}

  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
  SourceLocation getLocation() const {
    return SourceLocation::getFromPtrEncoding(getData1());
  }

protected:
  ImplicitCallPoint() {}
private:
  friend class ProgramPoint;
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() >= MinImplicitCallKind &&
           Location.getKind() <= MaxImplicitCallKind;
  }
};

/// Represents a program point just before an implicit call event.
///
/// Explicit calls will appear as PreStmt program points.
class PreImplicitCall : public ImplicitCallPoint {
public:
  PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
                  const ProgramPointTag *Tag = nullptr)
    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}

private:
  friend class ProgramPoint;
  PreImplicitCall() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PreImplicitCallKind;
  }
};

/// Represents a program point just after an implicit call event.
///
/// Explicit calls will appear as PostStmt program points.
class PostImplicitCall : public ImplicitCallPoint {
public:
  PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
                   const ProgramPointTag *Tag = nullptr)
    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}

private:
  friend class ProgramPoint;
  PostImplicitCall() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == PostImplicitCallKind;
  }
};

/// Represents a point when we begin processing an inlined call.
/// CallEnter uses the caller's location context.
class CallEnter : public ProgramPoint {
public:
  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, 
            const LocationContext *callerCtx)
    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}

  const Stmt *getCallExpr() const {
    return static_cast<const Stmt *>(getData1());
  }

  const StackFrameContext *getCalleeContext() const {
    return static_cast<const StackFrameContext *>(getData2());
  }

private:
  friend class ProgramPoint;
  CallEnter() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == CallEnterKind;
  }
};

/// Represents a point when we start the call exit sequence (for inlined call).
///
/// The call exit is simulated with a sequence of nodes, which occur between
/// CallExitBegin and CallExitEnd. The following operations occur between the
/// two program points:
/// - CallExitBegin
/// - Bind the return value
/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
/// - CallExitEnd
class CallExitBegin : public ProgramPoint {
public:
  // CallExitBegin uses the callee's location context.
  CallExitBegin(const StackFrameContext *L)
    : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {}

private:
  friend class ProgramPoint;
  CallExitBegin() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == CallExitBeginKind;
  }
};

/// Represents a point when we finish the call exit sequence (for inlined call).
/// \sa CallExitBegin
class CallExitEnd : public ProgramPoint {
public:
  // CallExitEnd uses the caller's location context.
  CallExitEnd(const StackFrameContext *CalleeCtx,
              const LocationContext *CallerCtx)
    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}

  const StackFrameContext *getCalleeContext() const {
    return static_cast<const StackFrameContext *>(getData1());
  }

private:
  friend class ProgramPoint;
  CallExitEnd() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == CallExitEndKind;
  }
};

/// This is a meta program point, which should be skipped by all the diagnostic
/// reasoning etc.
class EpsilonPoint : public ProgramPoint {
public:
  EpsilonPoint(const LocationContext *L, const void *Data1,
               const void *Data2 = nullptr,
               const ProgramPointTag *tag = nullptr)
    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}

  const void *getData() const { return getData1(); }

private:
  friend class ProgramPoint;
  EpsilonPoint() {}
  static bool isKind(const ProgramPoint &Location) {
    return Location.getKind() == EpsilonKind;
  }
};

/// ProgramPoints can be "tagged" as representing points specific to a given
/// analysis entity.  Tags are abstract annotations, with an associated
/// description and potentially other information.
class ProgramPointTag {
public:
  ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
  virtual ~ProgramPointTag();
  virtual StringRef getTagDescription() const = 0;    

protected:
  /// Used to implement 'isKind' in subclasses.
  const void *getTagKind() { return TagKind; }
  
private:
  const void *TagKind;
};

class SimpleProgramPointTag : public ProgramPointTag {
  std::string Desc;
public:
  SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
  StringRef getTagDescription() const override;
};

} // end namespace clang


namespace llvm { // Traits specialization for DenseMap

template <> struct DenseMapInfo<clang::ProgramPoint> {

static inline clang::ProgramPoint getEmptyKey() {
  uintptr_t x =
   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
}

static inline clang::ProgramPoint getTombstoneKey() {
  uintptr_t x =
   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
}

static unsigned getHashValue(const clang::ProgramPoint &Loc) {
  return Loc.getHashValue();
}

static bool isEqual(const clang::ProgramPoint &L,
                    const clang::ProgramPoint &R) {
  return L == R;
}

};
  
template <>
struct isPodLike<clang::ProgramPoint> { static const bool value = true; };

} // end namespace llvm

#endif
