//===- SVals.h - Abstract Values for Static 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 SVal, Loc, and NonLoc, classes that represent
//  abstract r-values for use with path-sensitive value tracking.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H

#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Casting.h"
#include <cassert>
#include <cstdint>
#include <utility>

//==------------------------------------------------------------------------==//
//  Base SVal types.
//==------------------------------------------------------------------------==//

namespace clang {

class CXXBaseSpecifier;
class DeclaratorDecl;
class FunctionDecl;
class LabelDecl;

namespace ento {

class BasicValueFactory;
class CompoundValData;
class LazyCompoundValData;
class MemRegion;
class PointerToMemberData;
class SValBuilder;
class TypedValueRegion;

namespace nonloc {

/// Sub-kinds for NonLoc values.
enum Kind {
#define NONLOC_SVAL(Id, Parent) Id ## Kind,
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
};

} // namespace nonloc

namespace loc {

/// Sub-kinds for Loc values.
enum Kind {
#define LOC_SVAL(Id, Parent) Id ## Kind,
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
};

} // namespace loc

/// SVal - This represents a symbolic expression, which can be either
///  an L-value or an R-value.
///
class SVal {
public:
  enum BaseKind {
    // The enumerators must be representable using 2 bits.
#define BASIC_SVAL(Id, Parent) Id ## Kind,
#define ABSTRACT_SVAL_WITH_KIND(Id, Parent) Id ## Kind,
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
  };
  enum { BaseBits = 2, BaseMask = 0x3 };

protected:
  const void *Data = nullptr;

  /// The lowest 2 bits are a BaseKind (0 -- 3).
  ///  The higher bits are an unsigned "kind" value.
  unsigned Kind = 0;

  explicit SVal(const void *d, bool isLoc, unsigned ValKind)
      : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}

  explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {}

public:
  explicit SVal() = default;

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

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

  unsigned getRawKind() const { return Kind; }
  BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
  unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }

  // This method is required for using SVal in a FoldingSetNode.  It
  // extracts a unique signature for this SVal object.
  void Profile(llvm::FoldingSetNodeID &ID) const {
    ID.AddInteger((unsigned) getRawKind());
    ID.AddPointer(Data);
  }

  bool operator==(const SVal &R) const {
    return getRawKind() == R.getRawKind() && Data == R.Data;
  }

  bool operator!=(const SVal &R) const {
    return !(*this == R);
  }

  bool isUnknown() const {
    return getRawKind() == UnknownValKind;
  }

  bool isUndef() const {
    return getRawKind() == UndefinedValKind;
  }

  bool isUnknownOrUndef() const {
    return getRawKind() <= UnknownValKind;
  }

  bool isValid() const {
    return getRawKind() > UnknownValKind;
  }

  bool isConstant() const;

  bool isConstant(int I) const;

  bool isZeroConstant() const;

  /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
  bool hasConjuredSymbol() const;

  /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
  /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
  /// Otherwise return 0.
  const FunctionDecl *getAsFunctionDecl() const;

  /// \brief If this SVal is a location and wraps a symbol, return that
  ///  SymbolRef. Otherwise return 0.
  ///
  /// Casts are ignored during lookup.
  /// \param IncludeBaseRegions The boolean that controls whether the search
  /// should continue to the base regions if the region is not symbolic.
  SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;

  /// Get the symbol in the SVal or its base region.
  SymbolRef getLocSymbolInBase() const;

  /// \brief If this SVal wraps a symbol return that SymbolRef.
  /// Otherwise, return 0.
  ///
  /// Casts are ignored during lookup.
  /// \param IncludeBaseRegions The boolean that controls whether the search
  /// should continue to the base regions if the region is not symbolic.
  SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;

  /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
  ///  return that expression.  Otherwise return NULL.
  const SymExpr *getAsSymbolicExpression() const;

  const SymExpr *getAsSymExpr() const;

  const MemRegion *getAsRegion() const;

  void dumpToStream(raw_ostream &OS) const;
  void dump() const;

  SymExpr::symbol_iterator symbol_begin() const {
    const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true);
    if (SE)
      return SE->symbol_begin();
    else
      return SymExpr::symbol_iterator();
  }

  SymExpr::symbol_iterator symbol_end() const { 
    return SymExpr::symbol_end();
  }
};

inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) {
  V.dumpToStream(os);
  return os;
}

class UndefinedVal : public SVal {
public:
  UndefinedVal() : SVal(UndefinedValKind) {}

private:
  friend class SVal;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == UndefinedValKind;
  }
};

class DefinedOrUnknownSVal : public SVal {
public:
  // We want calling these methods to be a compiler error since they are
  // tautologically false.
  bool isUndef() const = delete;
  bool isValid() const = delete;
  
protected:
  DefinedOrUnknownSVal() = default;
  explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
      : SVal(d, isLoc, ValKind) {}
  explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {}
  
private:
  friend class SVal;

  static bool isKind(const SVal& V) {
    return !V.isUndef();
  }
};
  
class UnknownVal : public DefinedOrUnknownSVal {
public:
  explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
  
private:
  friend class SVal;

  static bool isKind(const SVal &V) {
    return V.getBaseKind() == UnknownValKind;
  }
};

class DefinedSVal : public DefinedOrUnknownSVal {
public:
  // We want calling these methods to be a compiler error since they are
  // tautologically true/false.
  bool isUnknown() const = delete;
  bool isUnknownOrUndef() const = delete;
  bool isValid() const = delete;

protected:
  DefinedSVal() = default;
  explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
      : DefinedOrUnknownSVal(d, isLoc, ValKind) {}

private:
  friend class SVal;

  static bool isKind(const SVal& V) {
    return !V.isUnknownOrUndef();
  }
};

/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
class KnownSVal : public SVal {
  friend class SVal;

  KnownSVal() = default;

  static bool isKind(const SVal &V) {
    return !V.isUnknown();
  }

public:
  KnownSVal(const DefinedSVal &V) : SVal(V) {}
  KnownSVal(const UndefinedVal &V) : SVal(V) {}
};

class NonLoc : public DefinedSVal {
protected:
  NonLoc() = default;
  explicit NonLoc(unsigned SubKind, const void *d)
      : DefinedSVal(d, false, SubKind) {}

public:
  void dumpToStream(raw_ostream &Out) const;

  static bool isCompoundType(QualType T) {
    return T->isArrayType() || T->isRecordType() ||
           T->isComplexType() || T->isVectorType();
  }

private:
  friend class SVal;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == NonLocKind;
  }
};

class Loc : public DefinedSVal {
protected:
  Loc() = default;
  explicit Loc(unsigned SubKind, const void *D)
      : DefinedSVal(const_cast<void *>(D), true, SubKind) {}

public:
  void dumpToStream(raw_ostream &Out) const;

  static bool isLocType(QualType T) {
    return T->isAnyPointerType() || T->isBlockPointerType() || 
           T->isReferenceType() || T->isNullPtrType();
  }

private:
  friend class SVal;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == LocKind;
  }
};

//==------------------------------------------------------------------------==//
//  Subclasses of NonLoc.
//==------------------------------------------------------------------------==//

namespace nonloc {

/// \brief Represents symbolic expression.
class SymbolVal : public NonLoc {
public:
  SymbolVal() = delete;
  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); }

  SymbolRef getSymbol() const {
    return (const SymExpr *) Data;
  }

  bool isExpression() const {
    return !isa<SymbolData>(getSymbol());
  }

private:
  friend class SVal;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == NonLocKind &&
           V.getSubKind() == SymbolValKind;
  }

  static bool isKind(const NonLoc& V) {
    return V.getSubKind() == SymbolValKind;
  }
};

/// \brief Value representing integer constant.
class ConcreteInt : public NonLoc {
public:
  explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}

  const llvm::APSInt& getValue() const {
    return *static_cast<const llvm::APSInt *>(Data);
  }

  // Transfer functions for binary/unary operations on ConcreteInts.
  SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
                 const ConcreteInt& R) const;

  ConcreteInt evalComplement(SValBuilder &svalBuilder) const;

  ConcreteInt evalMinus(SValBuilder &svalBuilder) const;

private:
  friend class SVal;

  ConcreteInt() = default;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == NonLocKind &&
           V.getSubKind() == ConcreteIntKind;
  }

  static bool isKind(const NonLoc& V) {
    return V.getSubKind() == ConcreteIntKind;
  }
};

class LocAsInteger : public NonLoc {
  friend class ento::SValBuilder;

  explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
      : NonLoc(LocAsIntegerKind, &data) {
    // We do not need to represent loc::ConcreteInt as LocAsInteger,
    // as it'd collapse into a nonloc::ConcreteInt instead.
    assert(data.first.getBaseKind() == LocKind &&
           (data.first.getSubKind() == loc::MemRegionValKind ||
            data.first.getSubKind() == loc::GotoLabelKind));
  }

public:
  Loc getLoc() const {
    const std::pair<SVal, uintptr_t> *D =
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
    return D->first.castAs<Loc>();
  }

  Loc getPersistentLoc() const {
    const std::pair<SVal, uintptr_t> *D =
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
    const SVal& V = D->first;
    return V.castAs<Loc>();
  }

  unsigned getNumBits() const {
    const std::pair<SVal, uintptr_t> *D =
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
    return D->second;
  }

private:
  friend class SVal;

  LocAsInteger() = default;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == NonLocKind &&
           V.getSubKind() == LocAsIntegerKind;
  }

  static bool isKind(const NonLoc& V) {
    return V.getSubKind() == LocAsIntegerKind;
  }
};

class CompoundVal : public NonLoc {
  friend class ento::SValBuilder;

  explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}

public:
  const CompoundValData* getValue() const {
    return static_cast<const CompoundValData *>(Data);
  }

  using iterator = llvm::ImmutableList<SVal>::iterator;

  iterator begin() const;
  iterator end() const;

private:
  friend class SVal;

  CompoundVal() = default;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
  }

  static bool isKind(const NonLoc& V) {
    return V.getSubKind() == CompoundValKind;
  }
};

class LazyCompoundVal : public NonLoc {
  friend class ento::SValBuilder;

  explicit LazyCompoundVal(const LazyCompoundValData *D)
      : NonLoc(LazyCompoundValKind, D) {}

public:
  const LazyCompoundValData *getCVData() const {
    return static_cast<const LazyCompoundValData *>(Data);
  }

  const void *getStore() const;
  const TypedValueRegion *getRegion() const;

private:
  friend class SVal;

  LazyCompoundVal() = default;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == NonLocKind &&
           V.getSubKind() == LazyCompoundValKind;
  }

  static bool isKind(const NonLoc& V) {
    return V.getSubKind() == LazyCompoundValKind;
  }
};

/// \brief Value representing pointer-to-member.
///
/// This value is qualified as NonLoc because neither loading nor storing
/// operations are aplied to it. Instead, the analyzer uses the L-value coming
/// from pointer-to-member applied to an object.
/// This SVal is represented by a DeclaratorDecl which can be a member function
/// pointer or a member data pointer and a list of CXXBaseSpecifiers. This list
/// is required to accumulate the pointer-to-member cast history to figure out
/// the correct subobject field.
class PointerToMember : public NonLoc {
  friend class ento::SValBuilder;

public:
  using PTMDataType =
      llvm::PointerUnion<const DeclaratorDecl *, const PointerToMemberData *>;

  const PTMDataType getPTMData() const {
    return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data));
  }

  bool isNullMemberPointer() const {
    return getPTMData().isNull();
  }

  const DeclaratorDecl *getDecl() const;

  template<typename AdjustedDecl>
  const AdjustedDecl *getDeclAs() const {
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
  }

  using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator;

  iterator begin() const;
  iterator end() const;

private:
  friend class SVal;

  PointerToMember() = default;
  explicit PointerToMember(const PTMDataType D)
      : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {}

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == NonLocKind &&
           V.getSubKind() == PointerToMemberKind;
  }

  static bool isKind(const NonLoc& V) {
    return V.getSubKind() == PointerToMemberKind;
  }
};

} // namespace nonloc

//==------------------------------------------------------------------------==//
//  Subclasses of Loc.
//==------------------------------------------------------------------------==//

namespace loc {

class GotoLabel : public Loc {
public:
  explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) {
    assert(Label);
  }

  const LabelDecl *getLabel() const {
    return static_cast<const LabelDecl *>(Data);
  }

private:
  friend class SVal;

  GotoLabel() = default;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
  }

  static bool isKind(const Loc& V) {
    return V.getSubKind() == GotoLabelKind;
  }
};

class MemRegionVal : public Loc {
public:
  explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {
    assert(r);
  }

  /// \brief Get the underlining region.
  const MemRegion *getRegion() const {
    return static_cast<const MemRegion *>(Data);
  }

  /// \brief Get the underlining region and strip casts.
  const MemRegion* stripCasts(bool StripBaseCasts = true) const;

  template <typename REGION>
  const REGION* getRegionAs() const {
    return dyn_cast<REGION>(getRegion());
  }

  bool operator==(const MemRegionVal &R) const {
    return getRegion() == R.getRegion();
  }

  bool operator!=(const MemRegionVal &R) const {
    return getRegion() != R.getRegion();
  }

private:
  friend class SVal;

  MemRegionVal() = default;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == LocKind &&
           V.getSubKind() == MemRegionValKind;
  }

  static bool isKind(const Loc& V) {
    return V.getSubKind() == MemRegionValKind;
  }
};

class ConcreteInt : public Loc {
public:
  explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}

  const llvm::APSInt &getValue() const {
    return *static_cast<const llvm::APSInt *>(Data);
  }

  // Transfer functions for binary/unary operations on ConcreteInts.
  SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                 const ConcreteInt& R) const;

private:
  friend class SVal;

  ConcreteInt() = default;

  static bool isKind(const SVal& V) {
    return V.getBaseKind() == LocKind &&
           V.getSubKind() == ConcreteIntKind;
  }

  static bool isKind(const Loc& V) {
    return V.getSubKind() == ConcreteIntKind;
  }
};

} // namespace loc 

} // namespace ento

} // namespace clang

namespace llvm {

template <typename T> struct isPodLike;
template <> struct isPodLike<clang::ento::SVal> {
  static const bool value = true;
};

} // namespace llvm

#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
