//===- SVFVariables.h -- SVF Variables------------------------//
//
//                     SVF: Static Value-Flow Analysis
//
// Copyright (C) <2013->  <Yulei Sui>
//

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//===----------------------------------------------------------------------===//

/*
 * SVFVariables.h
 *
 *  Created on: Nov 11, 2013
 *      Author: Yulei Sui
 *  Refactored on: Nov 30, 2024
 *      Author: Xiao Cheng, Yulei Sui
 */

#ifndef INCLUDE_SVFIR_SVFVARIABLE_H_
#define INCLUDE_SVFIR_SVFVARIABLE_H_

#include "Graphs/GenericGraph.h"
#include "SVFIR/ObjTypeInfo.h"
#include "SVFIR/SVFStatements.h"

namespace SVF
{

class SVFVar;
/*
 * Program variables in SVFIR (based on PAG nodes)
 * These represent variables in the program analysis graph
 */
typedef GenericNode<SVFVar, SVFStmt> GenericPAGNodeTy;
class SVFVar : public GenericPAGNodeTy
{

    friend class SVFIRBuilder;
    friend class IRGraph;
    friend class SVFIR;
    friend class VFG;
    friend class GraphDBClient;

public:
    /// Node kinds for SVFIR variables:
    /// ValNode - LLVM pointer value
    /// ObjNode - Memory object
    /// RetValNode - Function return value
    /// VarargNode - Variable argument parameter
    /// GepValNode - Temporary value for field-sensitive analysis
    /// GepObjNode - Temporary object for field-sensitive analysis
    /// BaseObjNode - Base object for field-insensitive analysis
    /// DummyValNode/DummyObjNode - Nodes for non-LLVM values
    typedef GNodeK PNODEK;
    typedef s64_t GEdgeKind;

protected:
    /// Maps tracking incoming and outgoing edges by kind
    SVFStmt::KindToSVFStmtMapTy InEdgeKindToSetMap;
    SVFStmt::KindToSVFStmtMapTy OutEdgeKindToSetMap;

    inline const SVFStmt::KindToSVFStmtMapTy& getInEdgeKindToSetMap() const
    {
        return InEdgeKindToSetMap;
    }


    inline const SVFStmt::KindToSVFStmtMapTy& getOutEdgeKindToSetMap() const
    {
        return OutEdgeKindToSetMap;
    }


public:
    /// Standard constructor with ID, type and kind
    SVFVar(NodeID i, const SVFType* svfType, PNODEK k);

    /// Virtual destructor
    virtual ~SVFVar() {}

    /// Check if this variable represents a pointer
    virtual inline bool isPointer() const
    {
        assert(type && "type is null?");
        return type->isPointerTy();
    }

    /// Check if this variable represents constant data/metadata but not null pointer
    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return false;
    }

    /// Check if this node is isolated (no edges) in the SVFIR graph
    virtual bool isIsolatedNode() const;

    /// Get string name of the represented LLVM value
    virtual const std::string getValueName() const = 0;

    /// Get containing function, or null for globals/constants
    virtual inline const FunObjVar* getFunction() const
    {
        return nullptr;
    }

    /// Edge accessors and checkers
    //@{
    inline SVFStmt::SVFStmtSetTy& getIncomingEdges(SVFStmt::PEDGEK kind)
    {
        return InEdgeKindToSetMap[kind];
    }

    inline SVFStmt::SVFStmtSetTy& getOutgoingEdges(SVFStmt::PEDGEK kind)
    {
        return OutEdgeKindToSetMap[kind];
    }

    inline bool hasIncomingEdges(SVFStmt::PEDGEK kind) const
    {
        SVFStmt::KindToSVFStmtMapTy::const_iterator it = InEdgeKindToSetMap.find(kind);
        if (it != InEdgeKindToSetMap.end())
            return (!it->second.empty());
        else
            return false;
    }

    inline bool hasOutgoingEdges(SVFStmt::PEDGEK kind) const
    {
        SVFStmt::KindToSVFStmtMapTy::const_iterator it = OutEdgeKindToSetMap.find(kind);
        if (it != OutEdgeKindToSetMap.end())
            return (!it->second.empty());
        else
            return false;
    }

    /// Edge iterators
    inline SVFStmt::SVFStmtSetTy::iterator getIncomingEdgesBegin(SVFStmt::PEDGEK kind) const
    {
        SVFStmt::KindToSVFStmtMapTy::const_iterator it = InEdgeKindToSetMap.find(kind);
        assert(it!=InEdgeKindToSetMap.end() && "Edge kind not found");
        return it->second.begin();
    }

    inline SVFStmt::SVFStmtSetTy::iterator getIncomingEdgesEnd(SVFStmt::PEDGEK kind) const
    {
        SVFStmt::KindToSVFStmtMapTy::const_iterator it = InEdgeKindToSetMap.find(kind);
        assert(it!=InEdgeKindToSetMap.end() && "Edge kind not found");
        return it->second.end();
    }

    inline SVFStmt::SVFStmtSetTy::iterator getOutgoingEdgesBegin(SVFStmt::PEDGEK kind) const
    {
        SVFStmt::KindToSVFStmtMapTy::const_iterator it = OutEdgeKindToSetMap.find(kind);
        assert(it!=OutEdgeKindToSetMap.end() && "Edge kind not found");
        return it->second.begin();
    }

    inline SVFStmt::SVFStmtSetTy::iterator getOutgoingEdgesEnd(SVFStmt::PEDGEK kind) const
    {
        SVFStmt::KindToSVFStmtMapTy::const_iterator it = OutEdgeKindToSetMap.find(kind);
        assert(it!=OutEdgeKindToSetMap.end() && "Edge kind not found");
        return it->second.end();
    }
    //@}

    /// Type checking support for LLVM-style RTTI
    static inline bool classof(const SVFVar *)
    {
        return true;
    }

    static inline bool classof(const GenericPAGNodeTy * node)
    {
        return isSVFVarKind(node->getNodeKind());
    }

    static inline bool classof(const SVFValue* node)
    {
        return isSVFVarKind(node->getNodeKind());
    }

    /// Check if this pointer is in an uncalled function
    virtual bool ptrInUncalledFunction() const;

    /// Check if this variable represents constant/aggregate data
    virtual bool isConstDataOrAggData() const
    {
        return false;
    }


private:
    /// Edge management methods
    //@{
    inline void addInEdge(SVFStmt* inEdge)
    {
        GEdgeKind kind = inEdge->getEdgeKind();
        InEdgeKindToSetMap[kind].insert(inEdge);
        addIncomingEdge(inEdge);
    }

    inline void addOutEdge(SVFStmt* outEdge)
    {
        GEdgeKind kind = outEdge->getEdgeKind();
        OutEdgeKindToSetMap[kind].insert(outEdge);
        addOutgoingEdge(outEdge);
    }

    /// Check for incoming variable field GEP edges
    inline bool hasIncomingVariantGepEdge() const
    {
        SVFStmt::KindToSVFStmtMapTy::const_iterator it = InEdgeKindToSetMap.find(SVFStmt::Gep);
        if (it != InEdgeKindToSetMap.end())
        {
            for(auto gep : it->second)
            {
                if(SVFUtil::cast<GepStmt>(gep)->isVariantFieldGep())
                    return true;
            }
        }
        return false;
    }

public:
    /// Get string representation
    virtual const std::string toString() const;

    /// Debug dump to console
    void dump() const;

    /// Stream operator overload for output
    friend OutStream& operator<< (OutStream &o, const SVFVar &node)
    {
        o << node.toString();
        return o;
    }
};



/*
 * Value (Pointer) variable
 */
class ValVar: public SVFVar
{
    friend class GraphDBClient;

private:
    const ICFGNode* icfgNode; // icfgnode related to valvar

public:
    /// Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ValVar*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return isValVarKinds(node->getNodeKind());
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return isValVarKinds(node->getNodeKind());
    }
    static inline bool classof(const SVFValue* node)
    {
        return isValVarKinds(node->getNodeKind());
    }
    //@}

    /// Constructor
    ValVar(NodeID i, const SVFType* svfType, const ICFGNode* node, PNODEK ty = ValNode);
    /// Return name of a LLVM value
    inline const std::string getValueName() const
    {
        return getName();
    }

    const ICFGNode* getICFGNode() const
    {
        return icfgNode;
    }

    virtual const FunObjVar* getFunction() const;

    virtual const std::string toString() const;

    std::string getValVarNodeFieldsStmt() const;

};

/*
 * Memory Object variable
 */
class ObjVar: public SVFVar
{
    friend class GraphDBClient;

protected:
    /// Constructor
    ObjVar(NodeID i, const SVFType* svfType, PNODEK ty = ObjNode) :
        SVFVar(i, svfType, ty)
    {
    }
public:
    /// Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ObjVar*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return isObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return isObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const SVFValue* node)
    {
        return isObjVarKinds(node->getNodeKind());
    }
    //@}

    /// Return name of a LLVM value
    virtual const std::string getValueName() const
    {
        return getName();
    }

    virtual const std::string toString() const;

    std::string getObjVarNodeFieldsStmt() const;

};


/**
 * @brief Class representing a function argument variable in the SVFIR
 *
 * This class models function argument in the program analysis. It extends ValVar
 * to specifically handle function argument.
 */
class ArgValVar: public ValVar
{
    friend class GraphDBClient;

private:
    const FunObjVar* cgNode;
    u32_t argNo;

public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ArgValVar*)
    {
        return true;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == ArgValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == ArgValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == ArgValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == ArgValNode;
    }
    //@}

    /// Constructor
    ArgValVar(NodeID i, u32_t argNo, const ICFGNode* icn, const FunObjVar* callGraphNode,
              const SVFType* svfType);

    /// Return name of a LLVM value
    inline const std::string getValueName() const
    {
        return getName() + " (argument valvar)";
    }

    inline void addCGNodeFromDB(const FunObjVar* cgNode)
    {
        this->cgNode = cgNode;
    }

    virtual const FunObjVar* getFunction() const;

    const FunObjVar* getParent() const;

    ///  Return the index of this formal argument in its containing function.
    /// For example in "void foo(int a, float b)" a is 0 and b is 1.
    inline u32_t getArgNo() const
    {
        return argNo;
    }

    bool isArgOfUncalledFunction() const;

    virtual bool isPointer() const;

    virtual const std::string toString() const;
};


/*
 * Gep Value (Pointer) variable, this variable can be dynamic generated for field sensitive analysis
 * e.g. memcpy, temp gep value variable needs to be created
 * Each Gep Value variable is connected to base value variable via gep edge
 */
class GepValVar: public ValVar
{
    friend class GraphDBClient;

private:
    AccessPath ap;	// AccessPath
    const ValVar* base;	// base node
    const SVFType* gepValType;
    NodeID llvmVarID;


public:
    /// Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const GepValVar *)
    {
        return true;
    }
    static inline bool classof(const ValVar * node)
    {
        return node->getNodeKind() == SVFVar::GepValNode;
    }
    static inline bool classof(const SVFVar *node)
    {
        return node->getNodeKind() == SVFVar::GepValNode;
    }
    static inline bool classof(const GenericPAGNodeTy *node)
    {
        return node->getNodeKind() == SVFVar::GepValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::GepValNode;
    }

    inline const AccessPath& getAccessPath() const
    {
        return ap;
    }

    inline const void setAccessPath(const AccessPath* ap)
    {
        this->ap = *ap;
    }
    //@}

    /// Constructor
    GepValVar(const ValVar* baseNode, NodeID i, const AccessPath& ap,
              const SVFType* ty, const ICFGNode* node);

    /// offset of the base value variable
    inline APOffset getConstantFieldIdx() const
    {
        return ap.getConstantStructFldIdx();
    }

    /// Return the base object from which this GEP node came from.
    inline const ValVar* getBaseNode(void) const
    {
        return base;
    }
    inline void setBaseNode(const ValVar* baseNode)
    {
        base = baseNode;
    }

    /// Return name of a LLVM value
    inline const std::string getValueName() const
    {
        return getName() + "_" +
               std::to_string(getConstantFieldIdx());
    }

    virtual bool isPointer() const
    {
        return base->isPointer();
    }

    inline const SVFType* getType() const
    {
        return gepValType;
    }

    virtual const FunObjVar* getFunction() const
    {
        return base->getFunction();
    }

    virtual const std::string toString() const;

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return base->isConstDataOrAggDataButNotNullPtr();
    }
    virtual inline bool ptrInUncalledFunction() const
    {
        return base->ptrInUncalledFunction();
    }

    virtual inline bool isConstDataOrAggData() const
    {
        return base->isConstDataOrAggData();
    }

    /// Get the LLVM variable ID associated with this GepValVar
    inline NodeID getLLVMVarInstID() const
    {
        return llvmVarID;
    }

    /// Set the LLVM variable ID associated with this GepValVar
    inline void setLLVMVarInstID(NodeID id)
    {
        llvmVarID = id;
    }
};

/*
 * Base memory object variable (address-taken variables in LLVM-based languages)
 */
class BaseObjVar : public ObjVar
{
    friend class SVFIRBuilder;
    friend class GraphDBClient;

private:
    ObjTypeInfo* typeInfo;

    const ICFGNode* icfgNode; /// ICFGNode related to the creation of this object

public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const BaseObjVar*)
    {
        return true;
    }
    static inline bool classof(const ObjVar* node)
    {
        return isBaseObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const SVFVar* node)
    {
        return isBaseObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return isBaseObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const SVFValue* node)
    {
        return isBaseObjVarKinds(node->getNodeKind());
    }
    //@}

    /// Constructor
    BaseObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node, PNODEK ty = BaseObjNode)
        : ObjVar(i, ti->getType(), ty), typeInfo(ti), icfgNode(node)
    {
    }

    virtual const BaseObjVar* getBaseMemObj() const
    {
        return this;
    }

    inline const ObjTypeInfo* getTypeInfo() const
    {
        return typeInfo;
    }
    inline ObjTypeInfo* getTypeInfo()
    {
        return typeInfo;
    }

    /// Get the ICFGNode related to the creation of this object
    inline const ICFGNode* getICFGNode() const
    {
        return icfgNode;
    }

    /// Return name of a LLVM value
    inline const std::string getValueName() const
    {
        return getName() + " (base object)";
    }

    virtual const std::string toString() const;

    /// Get the memory object id
    inline NodeID getId() const
    {
        return id;
    }

    /// Get obj type
    const SVFType* getType() const
    {
        return typeInfo->getType();
    }

    /// Get the number of elements of this object
    u32_t getNumOfElements() const
    {
        return typeInfo->getNumOfElements();
    }

    /// Set the number of elements of this object
    void setNumOfElements(u32_t num)
    {
        return typeInfo->setNumOfElements(num);
    }

    /// Get max field offset limit
    u32_t getMaxFieldOffsetLimit() const
    {
        return typeInfo->getMaxFieldOffsetLimit();
    }


    /// Return true if its field limit is 0
    bool isFieldInsensitive() const
    {
        return getMaxFieldOffsetLimit() == 0;
    }

    /// Set the memory object to be field insensitive
    void setFieldInsensitive()
    {
        typeInfo->setMaxFieldOffsetLimit(0);
    }


    /// Set the memory object to be field sensitive (up to max field limit)
    void setFieldSensitive()
    {
        typeInfo->setMaxFieldOffsetLimit(typeInfo->getNumOfElements());
    }

    /// Whether it is a black hole object
    bool isBlackHoleObj() const;

    /// Get the byte size of this object
    u32_t getByteSizeOfObj() const
    {
        return typeInfo->getByteSizeOfObj();
    }

    /// Check if byte size is a const value
    bool isConstantByteSize() const
    {
        return typeInfo->isConstantByteSize();
    }


    /// object attributes methods
    //@{
    bool isFunction() const
    {
        return typeInfo->isFunction();
    }
    bool isGlobalObj() const
    {
        return typeInfo->isGlobalObj();
    }
    bool isStaticObj() const
    {
        return typeInfo->isStaticObj();
    }
    bool isStack() const
    {
        return typeInfo->isStack();
    }
    bool isHeap() const
    {
        return typeInfo->isHeap();
    }
    bool isStruct() const
    {
        return typeInfo->isStruct();
    }
    bool isArray() const
    {
        return typeInfo->isArray();
    }
    bool isVarStruct() const
    {
        return typeInfo->isVarStruct();
    }
    bool isVarArray() const
    {
        return typeInfo->isVarArray();
    }
    bool isConstantStruct() const
    {
        return typeInfo->isConstantStruct();
    }
    bool isConstantArray() const
    {
        return typeInfo->isConstantArray();
    }
    bool isConstDataOrConstGlobal() const
    {
        return typeInfo->isConstDataOrConstGlobal();
    }
    virtual inline bool isConstDataOrAggData() const
    {
        return typeInfo->isConstDataOrAggData();
    }
    //@}

    /// Clean up memory
    void destroy()
    {
        delete typeInfo;
        typeInfo = nullptr;
    }

    virtual const FunObjVar* getFunction() const;

};


/*
 * Gep Obj variable, this is dynamic generated for field sensitive analysis
 * Each gep obj variable is one field of a BaseObjVar (base)
 */
class GepObjVar: public ObjVar
{
    friend class GraphDBClient;


private:
    APOffset apOffset = 0;

    const BaseObjVar* base;

public:
    /// Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const GepObjVar*)
    {
        return true;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == SVFVar::GepObjNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::GepObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::GepObjNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::GepObjNode;
    }
    //@}

    /// Constructor
    GepObjVar(const BaseObjVar* baseObj, NodeID i,
              const APOffset& apOffset, PNODEK ty = GepObjNode)
        : ObjVar(i, baseObj->getType(), ty), apOffset(apOffset), base(baseObj)
    {
    }

    /// offset of the mem object
    inline APOffset getConstantFieldIdx() const
    {
        return apOffset;
    }

    /// Return the base object from which this GEP node came from.
    inline NodeID getBaseNode(void) const
    {
        return base->getId();
    }

    inline const BaseObjVar* getBaseObj() const
    {
        return base;
    }

    /// Return the type of this gep object
    inline virtual const SVFType* getType() const;


    /// Return name of a LLVM value
    inline const std::string getValueName() const
    {
        return getName() + "_" + std::to_string(apOffset);
    }

    virtual const FunObjVar* getFunction() const
    {
        return base->getFunction();
    }

    virtual const std::string toString() const;

    virtual inline bool ptrInUncalledFunction() const
    {
        return base->ptrInUncalledFunction();
    }

    virtual inline bool isConstDataOrAggData() const
    {
        return base->isConstDataOrAggData();
    }

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return base->isConstDataOrAggDataButNotNullPtr();
    }

    virtual bool isPointer() const
    {
        return base->isPointer();
    }
};



/**
 * @brief Class representing a heap object variable in the SVFIR
 *
 * This class models heap-allocated objects in the program analysis. It extends BaseObjVar
 * to specifically handle heap memory locations.
 */
class HeapObjVar: public BaseObjVar
{

    friend class GraphDBClient;

public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const HeapObjVar*)
    {
        return true;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == HeapObjNode;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == HeapObjNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == HeapObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == HeapObjNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == HeapObjNode;
    }
    //@}

    /// Constructor
    HeapObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node):
        BaseObjVar(i, ti, node, HeapObjNode)
    {
    }

    /// Return name of a LLVM value
    inline const std::string getValueName() const
    {
        return " (heap base object)";
    }

    virtual const std::string toString() const;
};


/**
 * @brief Represents a stack-allocated object variable in the SVFIR (SVF Intermediate Representation)
 * @inherits BaseObjVar
 *
 * This class models variables that are allocated on the stack in the program.
 * It provides type checking functionality through LLVM-style RTTI (Runtime Type Information)
 * methods like classof.
 */
class StackObjVar: public BaseObjVar
{

    friend class GraphDBClient;


public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const StackObjVar*)
    {
        return true;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == StackObjNode;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == StackObjNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == StackObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == StackObjNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == StackObjNode;
    }
    //@}

    /// Constructor
    StackObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node):
        BaseObjVar(i, ti, node, StackObjNode)
    {
    }

    /// Return name of a LLVM value
    inline const std::string getValueName() const
    {
        return " (stack base object)";
    }

    virtual const std::string toString() const;
};


class CallGraphNode;

class FunObjVar : public BaseObjVar
{
    friend class SVFIRBuilder;
    friend class LLVMModuleSet;
    friend class GraphDBClient;

protected:

    inline void updateExitBlock(SVFBasicBlock *bb)
    {
        exitBlock = bb;
    }

    inline void setLoopAndDomInfo(SVFLoopAndDomInfo *ld)
    {
        loopAndDom = ld;
    }
    inline bool getIsNotRet() const
    {
        return isNotRet;
    }
    inline const std::vector<const ArgValVar*> &getArgs() const
    {
        return allArgs;
    }

public:
    typedef SVFLoopAndDomInfo::BBSet BBSet;
    typedef SVFLoopAndDomInfo::BBList BBList;
    typedef SVFLoopAndDomInfo::LoopBBs LoopBBs;

    typedef BasicBlockGraph::IDToNodeMapTy::const_iterator const_bb_iterator;


private:
    bool isDecl;   /// return true if this function does not have a body
    bool intrinsic; /// return true if this function is an intrinsic function (e.g., llvm.dbg), which does not reside in the application code
    bool isAddrTaken; /// return true if this function is address-taken (for indirect call purposes)
    bool isUncalled;    /// return true if this function is never called
    bool isNotRet;   /// return true if this function never returns
    bool supVarArg;    /// return true if this function supports variable arguments
    const SVFFunctionType* funcType; /// FunctionType, which is different from the type (PointerType) of this SVF Function
    SVFLoopAndDomInfo* loopAndDom;  /// the loop and dominate information
    const FunObjVar * realDefFun;  /// the definition of a function across multiple modules
    BasicBlockGraph* bbGraph; /// the basic block graph of this function
    std::vector<const ArgValVar*> allArgs;    /// all formal arguments of this function
    const SVFBasicBlock *exitBlock;             /// a 'single' basic block having no successors and containing return instruction in a function


public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const FunObjVar*)
    {
        return true;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == FunObjNode;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == FunObjNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == FunObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == FunObjNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == FunObjNode;
    }
    //@}

    /// Constructor
    FunObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node);


    virtual ~FunObjVar()
    {
        delete loopAndDom;
        delete bbGraph;
    }

    void initFunObjVar(bool decl, bool intrinc, bool addr, bool uncalled, bool notret, bool vararg, const SVFFunctionType *ft,
                       SVFLoopAndDomInfo *ld, const FunObjVar *real, BasicBlockGraph *bbg,
                       const std::vector<const ArgValVar *> &allarg, const SVFBasicBlock *exit);

    void setRelDefFun(const FunObjVar *real)
    {
        realDefFun = real;
    }

    virtual const FunObjVar*getFunction() const;

    inline void addArgument(const ArgValVar *arg)
    {
        allArgs.push_back(arg);
    }
    inline bool isDeclaration() const
    {
        return isDecl;
    }

    inline bool isIntrinsic() const
    {
        return intrinsic;
    }

    inline bool hasAddressTaken() const
    {
        return isAddrTaken;
    }

    inline bool isVarArg() const
    {
        return supVarArg;
    }

    inline bool isUncalledFunction() const
    {
        return isUncalled;
    }

    inline bool hasReturn() const
    {
        return  !isNotRet;
    }

    /// Returns the FunctionType
    inline const SVFFunctionType* getFunctionType() const
    {
        return funcType;
    }

    /// Returns the FunctionType
    inline const SVFType* getReturnType() const
    {
        return funcType->getReturnType();
    }

    inline SVFLoopAndDomInfo* getLoopAndDomInfo() const
    {
        return loopAndDom;
    }

    inline const std::vector<const SVFBasicBlock*>& getReachableBBs() const
    {
        return loopAndDom->getReachableBBs();
    }

    inline void getExitBlocksOfLoop(const SVFBasicBlock* bb, BBList& exitbbs) const
    {
        return loopAndDom->getExitBlocksOfLoop(bb,exitbbs);
    }

    inline bool hasLoopInfo(const SVFBasicBlock* bb) const
    {
        return loopAndDom->hasLoopInfo(bb);
    }

    const LoopBBs& getLoopInfo(const SVFBasicBlock* bb) const
    {
        return loopAndDom->getLoopInfo(bb);
    }

    inline const SVFBasicBlock* getLoopHeader(const BBList& lp) const
    {
        return loopAndDom->getLoopHeader(lp);
    }

    inline bool loopContainsBB(const BBList& lp, const SVFBasicBlock* bb) const
    {
        return loopAndDom->loopContainsBB(lp,bb);
    }

    inline const Map<const SVFBasicBlock*,BBSet>& getDomTreeMap() const
    {
        return loopAndDom->getDomTreeMap();
    }

    inline const Map<const SVFBasicBlock*,BBSet>& getDomFrontierMap() const
    {
        return loopAndDom->getDomFrontierMap();
    }

    inline bool isLoopHeader(const SVFBasicBlock* bb) const
    {
        return loopAndDom->isLoopHeader(bb);
    }

    inline bool dominate(const SVFBasicBlock* bbKey, const SVFBasicBlock* bbValue) const
    {
        return loopAndDom->dominate(bbKey,bbValue);
    }

    inline bool postDominate(const SVFBasicBlock* bbKey, const SVFBasicBlock* bbValue) const
    {
        return loopAndDom->postDominate(bbKey,bbValue);
    }

    inline const FunObjVar* getDefFunForMultipleModule() const
    {
        if(realDefFun==nullptr)
            return this;
        return realDefFun;
    }

    void setBasicBlockGraph(BasicBlockGraph* graph)
    {
        this->bbGraph = graph;
    }

    BasicBlockGraph* getBasicBlockGraph()
    {
        return bbGraph;
    }

    const BasicBlockGraph* getBasicBlockGraph() const
    {
        return bbGraph;
    }

    inline bool hasBasicBlock() const
    {
        return bbGraph && bbGraph->begin() != bbGraph->end();
    }

    inline const SVFBasicBlock* getEntryBlock() const
    {
        assert(hasBasicBlock() && "function does not have any Basicblock, external function?");
        assert(bbGraph->begin()->second->getInEdges().size() == 0 && "the first basic block is not entry block");
        return bbGraph->begin()->second;
    }

    inline const SVFBasicBlock* getExitBB() const
    {
        assert(hasBasicBlock() && "function does not have any Basicblock, external function?");
        assert(exitBlock && "must have an exitBlock");
        return exitBlock;
    }

    inline void setExitBlock(SVFBasicBlock *bb)
    {
        assert(!exitBlock && "have already set exit Basicblock!");
        exitBlock = bb;
    }


    u32_t inline arg_size() const
    {
        return allArgs.size();
    }

    inline const ArgValVar*  getArg(u32_t idx) const
    {
        assert (idx < allArgs.size() && "getArg() out of range!");
        return allArgs[idx];
    }
    inline const SVFBasicBlock* front() const
    {
        return getEntryBlock();
    }

    inline const SVFBasicBlock* back() const
    {
        assert(hasBasicBlock() && "function does not have any Basicblock, external function?");
        /// Carefully! 'back' is just the last basic block of function,
        /// but not necessarily a exit basic block
        /// more refer to: https://github.com/SVF-tools/SVF/pull/1262
        return std::prev(bbGraph->end())->second;
    }

    inline const_bb_iterator begin() const
    {
        return bbGraph->begin();
    }

    inline const_bb_iterator end() const
    {
        return bbGraph->end();
    }

    virtual bool isIsolatedNode() const;

    virtual const std::string toString() const;
};
class FunValVar : public ValVar
{

    friend class GraphDBClient;

protected:
    inline void setFunction(const FunObjVar* cgn)
    {
        funObjVar = cgn;
    }

private:
    const FunObjVar* funObjVar;

public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const FunValVar*)
    {
        return true;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == FunValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == FunValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == FunValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == FunValNode;
    }
    //@}

    inline virtual const FunObjVar* getFunction() const
    {
        return funObjVar->getFunction();
    }

    /// Constructor
    FunValVar(NodeID i, const ICFGNode* icn, const FunObjVar* cgn, const SVFType* svfType);


    virtual bool isPointer() const
    {
        return true;
    }

    virtual const std::string toString() const;
};



class GlobalValVar : public ValVar
{
    friend class GraphDBClient;


public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const GlobalValVar*)
    {
        return true;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == GlobalValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == GlobalValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == GlobalValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == GlobalValNode;
    }
    //@}

    /// Constructor
    GlobalValVar(NodeID i, const ICFGNode* icn, const SVFType* svfType)
        : ValVar(i, svfType, icn, GlobalValNode)
    {
        type = svfType;
    }


    virtual const std::string toString() const;
};

class ConstAggValVar: public ValVar
{
    friend class GraphDBClient;


public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ConstAggValVar*)
    {
        return true;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == ConstAggValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == ConstAggValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == ConstAggValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == ConstAggValNode;
    }
    //@}

    /// Constructor
    ConstAggValVar(NodeID i, const ICFGNode* icn, const SVFType* svfTy)
        : ValVar(i, svfTy, icn, ConstAggValNode)
    {
        type = svfTy;
    }


    virtual bool isConstDataOrAggData() const
    {
        return true;
    }

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return true;
    }

    virtual const std::string toString() const;
};


class ConstDataValVar : public ValVar
{
    friend class GraphDBClient;


public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ConstDataValVar*)
    {
        return true;
    }
    static inline bool classof(const ValVar* node)
    {
        return isConstantDataValVar(node->getNodeKind());
    }
    static inline bool classof(const SVFVar* node)
    {
        return isConstantDataValVar(node->getNodeKind());
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return isConstantDataValVar(node->getNodeKind());
    }
    static inline bool classof(const SVFValue* node)
    {
        return isConstantDataValVar(node->getNodeKind());
    }
    //@}

    /// Constructor
    ConstDataValVar(NodeID i, const ICFGNode* icn, const SVFType* svfType,
                    PNODEK ty = ConstDataValNode)
        : ValVar(i, svfType, icn, ty)
    {

    }

    virtual bool isConstDataOrAggData() const
    {
        return true;
    }

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return true;
    }

    virtual const std::string toString() const;
};

class BlackHoleValVar : public ConstDataValVar
{

    friend class GraphDBClient;
public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const BlackHoleValVar*)
    {
        return true;
    }
    static inline bool classof(const ConstDataValVar* node)
    {
        return node->getNodeKind() == BlackHoleValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == BlackHoleValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == BlackHoleValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == BlackHoleValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == BlackHoleValNode;
    }
    //@}

    /// Constructor
    BlackHoleValVar(NodeID i, const SVFType* svfType, PNODEK ty = BlackHoleValNode)
        : ConstDataValVar(i,  nullptr, svfType, ty)
    {

    }

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return false;
    }

    virtual const std::string toString() const
    {
        return "BlackHoleValVar";
    }
};

class ConstFPValVar : public ConstDataValVar
{

    friend class GraphDBClient;

private:
    double dval;

public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ConstFPValVar*)
    {
        return true;
    }
    static inline bool classof(const ConstDataValVar* node)
    {
        return node->getNodeKind() == ConstFPValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == ConstFPValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == ConstFPValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == ConstFPValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == ConstFPValNode;
    }
    //@}

    inline double getFPValue() const
    {
        return dval;
    }

    /// Constructor
    ConstFPValVar(NodeID i, double dv,
                  const ICFGNode* icn, const SVFType* svfType)
        : ConstDataValVar(i, icn, svfType, ConstFPValNode), dval(dv)
    {
    }

    virtual const std::string toString() const;
};

class ConstIntValVar : public ConstDataValVar
{

    friend class GraphDBClient;


private:
    u64_t zval;
    s64_t sval;

public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ConstIntValVar*)
    {
        return true;
    }
    static inline bool classof(const ConstDataValVar* node)
    {
        return node->getNodeKind() == ConstIntValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == ConstIntValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == ConstIntValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == ConstIntValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == ConstIntValNode;
    }
    //@}

    s64_t getSExtValue() const
    {
        return sval;
    }


    u64_t getZExtValue() const
    {
        return zval;
    }

    /// Constructor
    ConstIntValVar(NodeID i, s64_t sv, u64_t zv, const ICFGNode* icn, const SVFType* svfType)
        : ConstDataValVar(i,  icn, svfType, ConstIntValNode), zval(zv), sval(sv)
    {

    }
    virtual const std::string toString() const;
};

class ConstNullPtrValVar : public ConstDataValVar
{
    friend class GraphDBClient;

public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ConstNullPtrValVar*)
    {
        return true;
    }
    static inline bool classof(const ConstDataValVar* node)
    {
        return node->getNodeKind() == ConstNullptrValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == ConstNullptrValNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == ConstNullptrValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == ConstNullptrValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == ConstNullptrValNode;
    }
    //@}

    /// Constructor
    ConstNullPtrValVar(NodeID i, const ICFGNode* icn, const SVFType* svfType)
        : ConstDataValVar(i,  icn, svfType, ConstNullptrValNode)
    {

    }

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return false;
    }

    virtual const std::string toString() const;
};

class GlobalObjVar : public BaseObjVar
{
    friend class GraphDBClient;


public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const GlobalObjVar*)
    {
        return true;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == GlobalObjNode;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == GlobalObjNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == GlobalObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == GlobalObjNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == GlobalObjNode;
    }
    //@}

    /// Constructor
    GlobalObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node,
                 PNODEK ty = GlobalObjNode): BaseObjVar(i, ti, node, ty)
    {

    }


    virtual const std::string toString() const;
};

class ConstAggObjVar : public BaseObjVar
{
    friend class GraphDBClient;


public:
    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
    //@{
    static inline bool classof(const ConstAggObjVar*)
    {
        return true;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == ConstAggObjNode;
    }

    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == ConstAggObjNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == ConstAggObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == ConstAggObjNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == ConstAggObjNode;
    }
    //@}

    /// Constructor
    ConstAggObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node)
        : BaseObjVar(i,  ti, node, ConstAggObjNode)
    {

    }

    virtual bool isConstDataOrAggData() const
    {
        return true;
    }

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return true;
    }

    virtual const std::string toString() const;
};

class ConstDataObjVar : public BaseObjVar
{
    friend class GraphDBClient;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const ConstDataObjVar*)
    {
        return true;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return isConstantDataObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const SVFVar* node)
    {
        return isConstantDataObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const ObjVar* node)
    {
        return isConstantDataObjVarKinds(node->getNodeKind());
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return isConstantDataObjVarKinds(node->getNodeKind());
    }

    static inline bool classof(const SVFValue* node)
    {
        return isConstantDataObjVarKinds(node->getNodeKind());
    }
    //@}

    /// Constructor
    ConstDataObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node, PNODEK ty = ConstDataObjNode)
        : BaseObjVar(i, ti, node, ty)
    {
    }

    virtual bool isConstDataOrAggData() const
    {
        return true;
    }

    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return true;
    }

    virtual const std::string toString() const;
};

class ConstFPObjVar : public ConstDataObjVar
{

    friend class GraphDBClient;


private:
    float dval;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const ConstFPObjVar*)
    {
        return true;
    }
    static inline bool classof(const ConstDataObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstFPObjNode;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstFPObjNode;
    }

    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstFPObjNode;
    }

    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstFPObjNode;
    }

    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::ConstFPObjNode;
    }

    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::ConstFPObjNode;
    }
    //@}

    /// Constructor
    ConstFPObjVar(NodeID i, double dv, ObjTypeInfo* ti, const ICFGNode* node)
        : ConstDataObjVar(i, ti, node, ConstFPObjNode), dval(dv)
    {
    }

    inline double getFPValue() const
    {
        return dval;
    }


    virtual const std::string toString() const;
};

class ConstIntObjVar : public ConstDataObjVar
{

    friend class GraphDBClient;



private:
    u64_t zval;
    s64_t sval;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const ConstIntObjVar*)
    {
        return true;
    }

    static inline bool classof(const ConstDataObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstIntObjNode;
    }

    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstIntObjNode;
    }

    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstIntObjNode;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstIntObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::ConstIntObjNode;
    }

    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::ConstIntObjNode;
    }

    s64_t getSExtValue() const
    {
        return sval;
    }


    u64_t getZExtValue() const
    {
        return zval;
    }
    //@}

    /// Constructor
    ConstIntObjVar(NodeID i, s64_t sv, u64_t zv, ObjTypeInfo* ti, const ICFGNode* node)
        : ConstDataObjVar(i, ti, node, ConstIntObjNode), zval(zv), sval(sv)
    {
    }

    virtual const std::string toString() const;
};

class ConstNullPtrObjVar : public ConstDataObjVar
{

    friend class GraphDBClient;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const ConstNullPtrObjVar*)
    {
        return true;
    }

    static inline bool classof(const ConstDataObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstNullptrObjNode;
    }

    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstNullptrObjNode;
    }

    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstNullptrObjNode;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == SVFVar::ConstNullptrObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::ConstNullptrObjNode;
    }

    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::ConstNullptrObjNode;
    }
    //@}

    /// Constructor
    ConstNullPtrObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node)
        : ConstDataObjVar(i, ti, node, ConstNullptrObjNode)
    {
    }
    virtual bool isConstDataOrAggDataButNotNullPtr() const
    {
        return false;
    }
    virtual const std::string toString() const;
};
/*
 * Unique Return node of a procedure
 */
class RetValPN : public ValVar
{
    friend class GraphDBClient;

protected:
    inline void setCallGraphNode(const FunObjVar* node)
    {
        callGraphNode = node;
    }

private:
    const FunObjVar* callGraphNode;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const RetValPN*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::RetValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == SVFVar::RetValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::RetValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::RetValNode;
    }
    //@}


    /// Constructor
    RetValPN(NodeID i, const FunObjVar* node, const SVFType* svfType, const ICFGNode* icn);

    inline const FunObjVar* getCallGraphNode() const
    {
        return callGraphNode;
    }

    virtual const FunObjVar* getFunction() const;

    virtual bool isPointer() const;

    /// Return name of a LLVM value
    const std::string getValueName() const;

    virtual const std::string toString() const;
};

/*
 * Unique vararg node of a procedure
 */
class VarArgValPN : public ValVar
{

    friend class GraphDBClient;

protected:
    inline void setCallGraphNode(const FunObjVar* node)
    {
        callGraphNode = node;
    }
private:
    const FunObjVar* callGraphNode;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const VarArgValPN*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::VarargValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == SVFVar::VarargValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::VarargValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::VarargValNode;
    }
    //@}

    /// Constructor
    VarArgValPN(NodeID i, const FunObjVar* node, const SVFType* svfType, const ICFGNode* icn)
        : ValVar(i, svfType, icn, VarargValNode), callGraphNode(node)
    {
        assert((node->isDeclaration() || icn) &&
               "VarArgValPN of a defined function must have a valid ICFGNode");
    }

    virtual const FunObjVar* getFunction() const;

    /// Return name of a LLVM value
    const std::string getValueName() const;

    virtual bool isPointer() const
    {
        return true;
    }
    virtual const std::string toString() const;
};

/*
 * Dummy variable without any LLVM value
 */
class DummyValVar: public ValVar
{
    friend class GraphDBClient;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const DummyValVar*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::DummyValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == SVFVar::DummyValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::DummyValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::DummyValNode;
    }
    //@}

    /// Constructor
    DummyValVar(NodeID i, const ICFGNode* node, const SVFType* svfType = SVFType::getSVFPtrType())
        : ValVar(i, svfType, node, DummyValNode)
    {
    }

    /// Return name of this node
    inline const std::string getValueName() const
    {
        return "dummyVal";
    }

    virtual bool isPointer() const
    {
        return true;
    }

    virtual const std::string toString() const;
};

/*
 * Represents an LLVM intrinsic call instruction (e.g. llvm.dbg.declare).
 * These are collected into valSyms but have no corresponding ICFGNode.
 */
class IntrinsicValVar: public ValVar
{
    friend class GraphDBClient;

public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const IntrinsicValVar*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::IntrinsicValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == SVFVar::IntrinsicValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::IntrinsicValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::IntrinsicValNode;
    }
    //@}

    IntrinsicValVar(NodeID i, const SVFType* svfType)
        : ValVar(i, svfType, nullptr, IntrinsicValNode)
    {
    }

    inline const std::string getValueName() const
    {
        return "intrinsicVal";
    }

    virtual const std::string toString() const;
};

/*
 * Represents an LLVM BasicBlock (label operand of br/switch).
 * Collected into valSyms as a branch operand but has no ICFGNode.
 */
class BasicBlockValVar: public ValVar
{
    friend class GraphDBClient;

public:
    static inline bool classof(const BasicBlockValVar*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::BasicBlockValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == SVFVar::BasicBlockValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::BasicBlockValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::BasicBlockValNode;
    }

    BasicBlockValVar(NodeID i, const SVFType* svfType)
        : ValVar(i, svfType, nullptr, BasicBlockValNode) {}

    inline const std::string getValueName() const
    {
        return "basicBlockVal";
    }
    virtual const std::string toString() const;
};

/*
 * Represents InlineAsm, DSOLocalEquivalent, and NoCFIValue.
 * These are non-instruction values related to inline assembly,
 * position-independent code (PIC), or control-flow integrity (CFI).
 * They have no corresponding ICFGNode.
 */
class AsmPCValVar: public ValVar
{
    friend class GraphDBClient;

public:
    static inline bool classof(const AsmPCValVar*)
    {
        return true;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::AsmPCValNode;
    }
    static inline bool classof(const ValVar* node)
    {
        return node->getNodeKind() == SVFVar::AsmPCValNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::AsmPCValNode;
    }
    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::AsmPCValNode;
    }

    AsmPCValVar(NodeID i, const SVFType* svfType)
        : ValVar(i, svfType, nullptr, AsmPCValNode) {}

    inline const std::string getValueName() const
    {
        return "asmPCVal";
    }
    virtual const std::string toString() const;
};

/*
 * Dummy object variable
 */
class DummyObjVar: public BaseObjVar
{

    friend class GraphDBClient;


public:
    //@{ Methods for support type inquiry through isa, cast, and dyn_cast:
    static inline bool classof(const DummyObjVar*)
    {
        return true;
    }
    static inline bool classof(const BaseObjVar* node)
    {
        return node->getNodeKind() == SVFVar::DummyObjNode;
    }
    static inline bool classof(const SVFVar* node)
    {
        return node->getNodeKind() == SVFVar::DummyObjNode;
    }
    static inline bool classof(const ObjVar* node)
    {
        return node->getNodeKind() == SVFVar::DummyObjNode;
    }
    static inline bool classof(const GenericPAGNodeTy* node)
    {
        return node->getNodeKind() == SVFVar::DummyObjNode;
    }

    static inline bool classof(const SVFValue* node)
    {
        return node->getNodeKind() == SVFVar::DummyObjNode;
    }
    //@}

    /// Constructor
    DummyObjVar(NodeID i, ObjTypeInfo* ti, const ICFGNode* node)
        : BaseObjVar(i, ti, node, DummyObjNode)
    {
    }

    /// Return name of this node
    inline const std::string getValueName() const
    {
        return "dummyObj";
    }

    virtual bool isPointer() const
    {
        return true;
    }

    virtual const std::string toString() const;
};

} // End namespace SVF

#endif /* INCLUDE_SVFIR_SVFVARIABLE_H_ */