//===-- ValueObject.h -------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ValueObject_h_
#define liblldb_ValueObject_h_

// C Includes
// C++ Includes
#include <functional>
#include <initializer_list>
#include <map>
#include <vector>

// Other libraries and framework includes
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"

// Project includes
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/UserID.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackID.h"
#include "lldb/Utility/SharedCluster.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

/// ValueObject:
///
/// This abstract class provides an interface to a particular value, be it a
/// register, a local or global variable,
/// that is evaluated in some particular scope.  The ValueObject also has the
/// capability of being the "child" of
/// some other variable object, and in turn of having children.
/// If a ValueObject is a root variable object - having no parent - then it must
/// be constructed with respect to some
/// particular ExecutionContextScope.  If it is a child, it inherits the
/// ExecutionContextScope from its parent.
/// The ValueObject will update itself if necessary before fetching its value,
/// summary, object description, etc.
/// But it will always update itself in the ExecutionContextScope with which it
/// was originally created.

/// A brief note on life cycle management for ValueObjects.  This is a little
/// tricky because a ValueObject can contain
/// various other ValueObjects - the Dynamic Value, its children, the
/// dereference value, etc.  Any one of these can be
/// handed out as a shared pointer, but for that contained value object to be
/// valid, the root object and potentially other
/// of the value objects need to stay around.
/// We solve this problem by handing out shared pointers to the Value Object and
/// any of its dependents using a shared
/// ClusterManager.  This treats each shared pointer handed out for the entire
/// cluster as a reference to the whole
/// cluster.  The whole cluster will stay around until the last reference is
/// released.
///
/// The ValueObject mostly handle this automatically, if a value object is made
/// with a Parent ValueObject, then it adds
/// itself to the ClusterManager of the parent.

/// It does mean that external to the ValueObjects we should only ever make
/// available ValueObjectSP's, never ValueObjects
/// or pointers to them.  So all the "Root level" ValueObject derived
/// constructors should be private, and
/// should implement a Create function that new's up object and returns a Shared
/// Pointer that it gets from the GetSP() method.
///
/// However, if you are making an derived ValueObject that will be contained in
/// a parent value object, you should just
/// hold onto a pointer to it internally, and by virtue of passing the parent
/// ValueObject into its constructor, it will
/// be added to the ClusterManager for the parent.  Then if you ever hand out a
/// Shared Pointer to the contained ValueObject,
/// just do so by calling GetSP() on the contained object.

class ValueObject : public UserID {
public:
  enum GetExpressionPathFormat {
    eGetExpressionPathFormatDereferencePointers = 1,
    eGetExpressionPathFormatHonorPointers
  };

  enum ValueObjectRepresentationStyle {
    eValueObjectRepresentationStyleValue = 1,
    eValueObjectRepresentationStyleSummary,
    eValueObjectRepresentationStyleLanguageSpecific,
    eValueObjectRepresentationStyleLocation,
    eValueObjectRepresentationStyleChildrenCount,
    eValueObjectRepresentationStyleType,
    eValueObjectRepresentationStyleName,
    eValueObjectRepresentationStyleExpressionPath
  };

  enum ExpressionPathScanEndReason {
    eExpressionPathScanEndReasonEndOfString = 1,      // out of data to parse
    eExpressionPathScanEndReasonNoSuchChild,          // child element not found
    eExpressionPathScanEndReasonNoSuchSyntheticChild, // (synthetic) child
                                                      // element not found
    eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for
                                                      // arrays
    eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be
                                                   // used
    eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be
                                                   // used
    eExpressionPathScanEndReasonFragileIVarNotAllowed,   // ObjC ivar expansion
                                                         // not allowed
    eExpressionPathScanEndReasonRangeOperatorNotAllowed, // [] not allowed by
                                                         // options
    eExpressionPathScanEndReasonRangeOperatorInvalid, // [] not valid on objects
                                                      // other than scalars,
                                                      // pointers or arrays
    eExpressionPathScanEndReasonArrayRangeOperatorMet, // [] is good for arrays,
                                                       // but I cannot parse it
    eExpressionPathScanEndReasonBitfieldRangeOperatorMet, // [] is good for
                                                          // bitfields, but I
                                                          // cannot parse after
                                                          // it
    eExpressionPathScanEndReasonUnexpectedSymbol, // something is malformed in
                                                  // the expression
    eExpressionPathScanEndReasonTakingAddressFailed,   // impossible to apply &
                                                       // operator
    eExpressionPathScanEndReasonDereferencingFailed,   // impossible to apply *
                                                       // operator
    eExpressionPathScanEndReasonRangeOperatorExpanded, // [] was expanded into a
                                                       // VOList
    eExpressionPathScanEndReasonSyntheticValueMissing, // getting the synthetic
                                                       // children failed
    eExpressionPathScanEndReasonUnknown = 0xFFFF
  };

  enum ExpressionPathEndResultType {
    eExpressionPathEndResultTypePlain = 1,       // anything but...
    eExpressionPathEndResultTypeBitfield,        // a bitfield
    eExpressionPathEndResultTypeBoundedRange,    // a range [low-high]
    eExpressionPathEndResultTypeUnboundedRange,  // a range []
    eExpressionPathEndResultTypeValueObjectList, // several items in a VOList
    eExpressionPathEndResultTypeInvalid = 0xFFFF
  };

  enum ExpressionPathAftermath {
    eExpressionPathAftermathNothing = 1, // just return it
    eExpressionPathAftermathDereference, // dereference the target
    eExpressionPathAftermathTakeAddress  // take target's address
  };

  enum ClearUserVisibleDataItems {
    eClearUserVisibleDataItemsNothing = 1u << 0,
    eClearUserVisibleDataItemsValue = 1u << 1,
    eClearUserVisibleDataItemsSummary = 1u << 2,
    eClearUserVisibleDataItemsLocation = 1u << 3,
    eClearUserVisibleDataItemsDescription = 1u << 4,
    eClearUserVisibleDataItemsSyntheticChildren = 1u << 5,
    eClearUserVisibleDataItemsValidator = 1u << 6,
    eClearUserVisibleDataItemsAllStrings =
        eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary |
        eClearUserVisibleDataItemsLocation |
        eClearUserVisibleDataItemsDescription,
    eClearUserVisibleDataItemsAll = 0xFFFF
  };

  struct GetValueForExpressionPathOptions {
    enum class SyntheticChildrenTraversal {
      None,
      ToSynthetic,
      FromSynthetic,
      Both
    };

    bool m_check_dot_vs_arrow_syntax;
    bool m_no_fragile_ivar;
    bool m_allow_bitfields_syntax;
    SyntheticChildrenTraversal m_synthetic_children_traversal;

    GetValueForExpressionPathOptions(
        bool dot = false, bool no_ivar = false, bool bitfield = true,
        SyntheticChildrenTraversal synth_traverse =
            SyntheticChildrenTraversal::ToSynthetic)
        : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar),
          m_allow_bitfields_syntax(bitfield),
          m_synthetic_children_traversal(synth_traverse) {}

    GetValueForExpressionPathOptions &DoCheckDotVsArrowSyntax() {
      m_check_dot_vs_arrow_syntax = true;
      return *this;
    }

    GetValueForExpressionPathOptions &DontCheckDotVsArrowSyntax() {
      m_check_dot_vs_arrow_syntax = false;
      return *this;
    }

    GetValueForExpressionPathOptions &DoAllowFragileIVar() {
      m_no_fragile_ivar = false;
      return *this;
    }

    GetValueForExpressionPathOptions &DontAllowFragileIVar() {
      m_no_fragile_ivar = true;
      return *this;
    }

    GetValueForExpressionPathOptions &DoAllowBitfieldSyntax() {
      m_allow_bitfields_syntax = true;
      return *this;
    }

    GetValueForExpressionPathOptions &DontAllowBitfieldSyntax() {
      m_allow_bitfields_syntax = false;
      return *this;
    }

    GetValueForExpressionPathOptions &
    SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) {
      m_synthetic_children_traversal = traverse;
      return *this;
    }

    static const GetValueForExpressionPathOptions DefaultOptions() {
      static GetValueForExpressionPathOptions g_default_options;

      return g_default_options;
    }
  };

  class EvaluationPoint {
  public:
    EvaluationPoint();

    EvaluationPoint(ExecutionContextScope *exe_scope,
                    bool use_selected = false);

    EvaluationPoint(const EvaluationPoint &rhs);

    ~EvaluationPoint();

    const ExecutionContextRef &GetExecutionContextRef() const {
      return m_exe_ctx_ref;
    }

    // Set the EvaluationPoint to the values in exe_scope,
    // Return true if the Evaluation Point changed.
    // Since the ExecutionContextScope is always going to be valid currently,
    // the Updated Context will also always be valid.

    //        bool
    //        SetContext (ExecutionContextScope *exe_scope);

    void SetIsConstant() {
      SetUpdated();
      m_mod_id.SetInvalid();
    }

    bool IsConstant() const { return !m_mod_id.IsValid(); }

    ProcessModID GetModID() const { return m_mod_id; }

    void SetUpdateID(ProcessModID new_id) { m_mod_id = new_id; }

    void SetNeedsUpdate() { m_needs_update = true; }

    void SetUpdated();

    bool NeedsUpdating(bool accept_invalid_exe_ctx) {
      SyncWithProcessState(accept_invalid_exe_ctx);
      return m_needs_update;
    }

    bool IsValid() {
      const bool accept_invalid_exe_ctx = false;
      if (!m_mod_id.IsValid())
        return false;
      else if (SyncWithProcessState(accept_invalid_exe_ctx)) {
        if (!m_mod_id.IsValid())
          return false;
      }
      return true;
    }

    void SetInvalid() {
      // Use the stop id to mark us as invalid, leave the thread id and the
      // stack id around for logging and
      // history purposes.
      m_mod_id.SetInvalid();

      // Can't update an invalid state.
      m_needs_update = false;
    }

  private:
    bool SyncWithProcessState(bool accept_invalid_exe_ctx);

    ProcessModID m_mod_id; // This is the stop id when this ValueObject was last
                           // evaluated.
    ExecutionContextRef m_exe_ctx_ref;
    bool m_needs_update;
  };

  virtual ~ValueObject();

  const EvaluationPoint &GetUpdatePoint() const { return m_update_point; }

  EvaluationPoint &GetUpdatePoint() { return m_update_point; }

  const ExecutionContextRef &GetExecutionContextRef() const {
    return m_update_point.GetExecutionContextRef();
  }

  lldb::TargetSP GetTargetSP() const {
    return m_update_point.GetExecutionContextRef().GetTargetSP();
  }

  lldb::ProcessSP GetProcessSP() const {
    return m_update_point.GetExecutionContextRef().GetProcessSP();
  }

  lldb::ThreadSP GetThreadSP() const {
    return m_update_point.GetExecutionContextRef().GetThreadSP();
  }

  lldb::StackFrameSP GetFrameSP() const {
    return m_update_point.GetExecutionContextRef().GetFrameSP();
  }

  void SetNeedsUpdate();

  CompilerType GetCompilerType();

  // this vends a TypeImpl that is useful at the SB API layer
  virtual TypeImpl GetTypeImpl();

  virtual bool CanProvideValue();

  //------------------------------------------------------------------
  // Subclasses must implement the functions below.
  //------------------------------------------------------------------
  virtual uint64_t GetByteSize() = 0;

  virtual lldb::ValueType GetValueType() const = 0;

  //------------------------------------------------------------------
  // Subclasses can implement the functions below.
  //------------------------------------------------------------------
  virtual ConstString GetTypeName();

  virtual ConstString GetDisplayTypeName();

  virtual ConstString GetQualifiedTypeName();

  virtual lldb::LanguageType GetObjectRuntimeLanguage();

  virtual uint32_t
  GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr);

  virtual bool IsPointerType();

  virtual bool IsArrayType();

  virtual bool IsScalarType();

  virtual bool IsPointerOrReferenceType();

  virtual bool IsPossibleDynamicType();

  bool IsNilReference();

  bool IsUninitializedReference();

  virtual bool IsBaseClass() { return false; }

  bool IsBaseClass(uint32_t &depth);

  virtual bool IsDereferenceOfParent() { return false; }

  bool IsIntegerType(bool &is_signed);

  virtual bool GetBaseClassPath(Stream &s);

  virtual void GetExpressionPath(
      Stream &s, bool qualify_cxx_base_classes,
      GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers);

  lldb::ValueObjectSP GetValueForExpressionPath(
      llvm::StringRef expression,
      ExpressionPathScanEndReason *reason_to_stop = nullptr,
      ExpressionPathEndResultType *final_value_type = nullptr,
      const GetValueForExpressionPathOptions &options =
          GetValueForExpressionPathOptions::DefaultOptions(),
      ExpressionPathAftermath *final_task_on_target = nullptr);

  virtual bool IsInScope() { return true; }

  virtual lldb::offset_t GetByteOffset() { return 0; }

  virtual uint32_t GetBitfieldBitSize() { return 0; }

  virtual uint32_t GetBitfieldBitOffset() { return 0; }

  bool IsBitfield() {
    return (GetBitfieldBitSize() != 0) || (GetBitfieldBitOffset() != 0);
  }

  virtual bool IsArrayItemForPointer() { return m_is_array_item_for_pointer; }

  virtual const char *GetValueAsCString();

  virtual bool GetValueAsCString(const lldb_private::TypeFormatImpl &format,
                                 std::string &destination);

  bool GetValueAsCString(lldb::Format format, std::string &destination);

  virtual uint64_t GetValueAsUnsigned(uint64_t fail_value,
                                      bool *success = nullptr);

  virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = nullptr);

  virtual bool SetValueFromCString(const char *value_str, Error &error);

  // Return the module associated with this value object in case the
  // value is from an executable file and might have its data in
  // sections of the file. This can be used for variables.
  virtual lldb::ModuleSP GetModule();

  ValueObject *GetRoot();

  // Given a ValueObject, loop over itself and its parent, and its parent's
  // parent, ..
  // until either the given callback returns false, or you end up at a null
  // pointer
  ValueObject *FollowParentChain(std::function<bool(ValueObject *)>);

  virtual bool GetDeclaration(Declaration &decl);

  //------------------------------------------------------------------
  // The functions below should NOT be modified by subclasses
  //------------------------------------------------------------------
  const Error &GetError();

  const ConstString &GetName() const;

  virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create);

  // this will always create the children if necessary
  lldb::ValueObjectSP
  GetChildAtIndexPath(const std::initializer_list<size_t> &idxs,
                      size_t *index_of_error = nullptr);

  lldb::ValueObjectSP GetChildAtIndexPath(const std::vector<size_t> &idxs,
                                          size_t *index_of_error = nullptr);

  lldb::ValueObjectSP GetChildAtIndexPath(
      const std::initializer_list<std::pair<size_t, bool>> &idxs,
      size_t *index_of_error = nullptr);

  lldb::ValueObjectSP
  GetChildAtIndexPath(const std::vector<std::pair<size_t, bool>> &idxs,
                      size_t *index_of_error = nullptr);

  // this will always create the children if necessary
  lldb::ValueObjectSP
  GetChildAtNamePath(const std::initializer_list<ConstString> &names,
                     ConstString *name_of_error = nullptr);

  lldb::ValueObjectSP GetChildAtNamePath(const std::vector<ConstString> &names,
                                         ConstString *name_of_error = nullptr);

  lldb::ValueObjectSP GetChildAtNamePath(
      const std::initializer_list<std::pair<ConstString, bool>> &names,
      ConstString *name_of_error = nullptr);

  lldb::ValueObjectSP
  GetChildAtNamePath(const std::vector<std::pair<ConstString, bool>> &names,
                     ConstString *name_of_error = nullptr);

  virtual lldb::ValueObjectSP GetChildMemberWithName(const ConstString &name,
                                                     bool can_create);

  virtual size_t GetIndexOfChildWithName(const ConstString &name);

  size_t GetNumChildren(uint32_t max = UINT32_MAX);

  const Value &GetValue() const;

  Value &GetValue();

  virtual bool ResolveValue(Scalar &scalar);

  // return 'false' whenever you set the error, otherwise
  // callers may assume true means everything is OK - this will
  // break breakpoint conditions among potentially a few others
  virtual bool IsLogicalTrue(Error &error);

  virtual const char *GetLocationAsCString();

  const char *
  GetSummaryAsCString(lldb::LanguageType lang = lldb::eLanguageTypeUnknown);

  bool
  GetSummaryAsCString(TypeSummaryImpl *summary_ptr, std::string &destination,
                      lldb::LanguageType lang = lldb::eLanguageTypeUnknown);

  bool GetSummaryAsCString(std::string &destination,
                           const TypeSummaryOptions &options);

  bool GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
                           std::string &destination,
                           const TypeSummaryOptions &options);

  std::pair<TypeValidatorResult, std::string> GetValidationStatus();

  const char *GetObjectDescription();

  bool HasSpecialPrintableRepresentation(
      ValueObjectRepresentationStyle val_obj_display,
      lldb::Format custom_format);

  enum class PrintableRepresentationSpecialCases : bool {
    eDisable = false,
    eAllow = true
  };

  bool
  DumpPrintableRepresentation(Stream &s,
                              ValueObjectRepresentationStyle val_obj_display =
                                  eValueObjectRepresentationStyleSummary,
                              lldb::Format custom_format = lldb::eFormatInvalid,
                              PrintableRepresentationSpecialCases special =
                                  PrintableRepresentationSpecialCases::eAllow,
                              bool do_dump_error = true);
  bool GetValueIsValid() const;

  // If you call this on a newly created ValueObject, it will always return
  // false.
  bool GetValueDidChange();

  bool UpdateValueIfNeeded(bool update_format = true);

  bool UpdateFormatsIfNeeded();

  lldb::ValueObjectSP GetSP() { return m_manager->GetSharedPointer(this); }

  void SetName(const ConstString &name);

  virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
                                    AddressType *address_type = nullptr);

  lldb::addr_t GetPointerValue(AddressType *address_type = nullptr);

  lldb::ValueObjectSP GetSyntheticChild(const ConstString &key) const;

  lldb::ValueObjectSP GetSyntheticArrayMember(size_t index, bool can_create);

  lldb::ValueObjectSP GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
                                                bool can_create);

  lldb::ValueObjectSP GetSyntheticExpressionPathChild(const char *expression,
                                                      bool can_create);

  virtual lldb::ValueObjectSP
  GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type,
                            bool can_create,
                            ConstString name_const_str = ConstString());

  virtual lldb::ValueObjectSP
  GetSyntheticBase(uint32_t offset, const CompilerType &type, bool can_create,
                   ConstString name_const_str = ConstString());

  virtual lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType);

  lldb::DynamicValueType GetDynamicValueType();

  virtual lldb::ValueObjectSP GetStaticValue();

  virtual lldb::ValueObjectSP GetNonSyntheticValue();

  lldb::ValueObjectSP GetSyntheticValue(bool use_synthetic = true);

  virtual bool HasSyntheticValue();

  SwiftASTContext *GetSwiftASTContext();

  virtual bool IsSynthetic() { return false; }

  lldb::ValueObjectSP
  GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue,
                                        bool synthValue);

  virtual lldb::ValueObjectSP CreateConstantValue(const ConstString &name);

  virtual lldb::ValueObjectSP Dereference(Error &error);

  virtual lldb::ValueObjectSP AddressOf(Error &error);

  virtual lldb::addr_t GetLiveAddress() { return LLDB_INVALID_ADDRESS; }

  virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
                              AddressType address_type = eAddressTypeLoad) {}

  // Find the address of the C++ vtable pointer
  virtual lldb::addr_t GetCPPVTableAddress(AddressType &address_type);

  virtual lldb::ValueObjectSP Cast(const CompilerType &compiler_type);

  virtual lldb::ValueObjectSP CastPointerType(const char *name,
                                              CompilerType &ast_type);

  virtual lldb::ValueObjectSP CastPointerType(const char *name,
                                              lldb::TypeSP &type_sp);

  // The backing bits of this value object were updated, clear any
  // descriptive string, so we know we have to refetch them
  virtual void ValueUpdated() {
    ClearUserVisibleData(eClearUserVisibleDataItemsValue |
                         eClearUserVisibleDataItemsSummary |
                         eClearUserVisibleDataItemsDescription);
  }

  virtual bool IsDynamic() { return false; }

  virtual bool DoesProvideSyntheticValue() { return false; }

  virtual bool IsSyntheticChildrenGenerated();

  virtual void SetSyntheticChildrenGenerated(bool b);

  virtual SymbolContextScope *GetSymbolContextScope();

  void Dump(Stream &s);

  void Dump(Stream &s, const DumpValueObjectOptions &options);

  static lldb::ValueObjectSP
  CreateValueObjectFromExpression(llvm::StringRef name,
                                  llvm::StringRef expression,
                                  const ExecutionContext &exe_ctx);

  static lldb::ValueObjectSP
  CreateValueObjectFromExpression(llvm::StringRef name,
                                  llvm::StringRef expression,
                                  const ExecutionContext &exe_ctx,
                                  const EvaluateExpressionOptions &options);

  static lldb::ValueObjectSP
  CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
                               const ExecutionContext &exe_ctx,
                               CompilerType type);

  static lldb::ValueObjectSP
  CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data,
                            const ExecutionContext &exe_ctx, CompilerType type);

  void LogValueObject(Log *log);

  void LogValueObject(Log *log, const DumpValueObjectOptions &options);

  lldb::ValueObjectSP Persist();

  // returns true if this is a char* or a char[]
  // if it is a char* and check_pointer is true,
  // it also checks that the pointer is valid
  bool IsCStringContainer(bool check_pointer = false);

  std::pair<size_t, bool>
  ReadPointedString(lldb::DataBufferSP &buffer_sp, Error &error,
                    uint32_t max_length = 0, bool honor_array = true,
                    lldb::Format item_format = lldb::eFormatCharArray);

  virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
                                uint32_t item_count = 1);

  virtual uint64_t GetData(DataExtractor &data, Error &error);

  virtual bool SetData(DataExtractor &data, Error &error);

  virtual bool GetIsConstant() const { return m_update_point.IsConstant(); }

  bool NeedsUpdating() {
    const bool accept_invalid_exe_ctx =
        (CanUpdateWithInvalidExecutionContext() == eLazyBoolYes);
    return m_update_point.NeedsUpdating(accept_invalid_exe_ctx);
  }

  void SetIsConstant() { m_update_point.SetIsConstant(); }

  lldb::Format GetFormat() const;

  virtual void SetFormat(lldb::Format format) {
    if (format != m_format)
      ClearUserVisibleData(eClearUserVisibleDataItemsValue);
    m_format = format;
  }

  virtual lldb::LanguageType GetPreferredDisplayLanguage();

  void SetPreferredDisplayLanguage(lldb::LanguageType);

  lldb::TypeSummaryImplSP GetSummaryFormat() {
    UpdateFormatsIfNeeded();
    return m_type_summary_sp;
  }

  void SetSummaryFormat(lldb::TypeSummaryImplSP format) {
    m_type_summary_sp = format;
    ClearUserVisibleData(eClearUserVisibleDataItemsSummary);
  }

  lldb::TypeValidatorImplSP GetValidator() {
    UpdateFormatsIfNeeded();
    return m_type_validator_sp;
  }

  void SetValidator(lldb::TypeValidatorImplSP format) {
    m_type_validator_sp = format;
    ClearUserVisibleData(eClearUserVisibleDataItemsValidator);
  }

  void SetValueFormat(lldb::TypeFormatImplSP format) {
    m_type_format_sp = format;
    ClearUserVisibleData(eClearUserVisibleDataItemsValue);
  }

  lldb::TypeFormatImplSP GetValueFormat() {
    UpdateFormatsIfNeeded();
    return m_type_format_sp;
  }

  void SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) {
    if (synth_sp.get() == m_synthetic_children_sp.get())
      return;
    ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren);
    m_synthetic_children_sp = synth_sp;
  }

  lldb::SyntheticChildrenSP GetSyntheticChildren() {
    UpdateFormatsIfNeeded();
    return m_synthetic_children_sp;
  }

  // Use GetParent for display purposes, but if you want to tell the parent to
  // update itself
  // then use m_parent.  The ValueObjectDynamicValue's parent is not the correct
  // parent for
  // displaying, they are really siblings, so for display it needs to route
  // through to its grandparent.
  virtual ValueObject *GetParent() { return m_parent; }

  virtual const ValueObject *GetParent() const { return m_parent; }

  ValueObject *GetNonBaseClassParent();

  void SetAddressTypeOfChildren(AddressType at) {
    m_address_type_of_ptr_or_ref_children = at;
  }

  AddressType GetAddressTypeOfChildren();

  void SetHasCompleteType() { m_did_calculate_complete_objc_class_type = true; }

  //------------------------------------------------------------------
  /// Find out if a ValueObject might have children.
  ///
  /// This call is much more efficient than CalculateNumChildren() as
  /// it doesn't need to complete the underlying type. This is designed
  /// to be used in a UI environment in order to detect if the
  /// disclosure triangle should be displayed or not.
  ///
  /// This function returns true for class, union, structure,
  /// pointers, references, arrays and more. Again, it does so without
  /// doing any expensive type completion.
  ///
  /// @return
  ///     Returns \b true if the ValueObject might have children, or \b
  ///     false otherwise.
  //------------------------------------------------------------------
  virtual bool MightHaveChildren();

  virtual lldb::VariableSP GetVariable() { return nullptr; }

  virtual bool IsRuntimeSupportValue();

  virtual uint64_t GetLanguageFlags();

  virtual void SetLanguageFlags(uint64_t flags);

protected:
  typedef ClusterManager<ValueObject> ValueObjectManager;

  class ChildrenManager {
  public:
    ChildrenManager() : m_mutex(), m_children(), m_children_count(0) {}

    bool HasChildAtIndex(size_t idx) {
      std::lock_guard<std::recursive_mutex> guard(m_mutex);
      return (m_children.find(idx) != m_children.end());
    }

    ValueObject *GetChildAtIndex(size_t idx) {
      std::lock_guard<std::recursive_mutex> guard(m_mutex);
      const auto iter = m_children.find(idx);
      return ((iter == m_children.end()) ? nullptr : iter->second);
    }

    void SetChildAtIndex(size_t idx, ValueObject *valobj) {
      // we do not need to be mutex-protected to make a pair
      ChildrenPair pair(idx, valobj);
      std::lock_guard<std::recursive_mutex> guard(m_mutex);
      m_children.insert(pair);
    }

    void SetChildrenCount(size_t count) { Clear(count); }

    size_t GetChildrenCount() { return m_children_count; }

    void Clear(size_t new_count = 0) {
      std::lock_guard<std::recursive_mutex> guard(m_mutex);
      m_children_count = new_count;
      m_children.clear();
    }

  private:
    typedef std::map<size_t, ValueObject *> ChildrenMap;
    typedef ChildrenMap::iterator ChildrenIterator;
    typedef ChildrenMap::value_type ChildrenPair;
    std::recursive_mutex m_mutex;
    ChildrenMap m_children;
    size_t m_children_count;
  };

  //------------------------------------------------------------------
  // Classes that inherit from ValueObject can see and modify these
  //------------------------------------------------------------------
  ValueObject
      *m_parent; // The parent value object, or nullptr if this has no parent
  ValueObject *m_root; // The root of the hierarchy for this ValueObject (or
                       // nullptr if never calculated)
  EvaluationPoint m_update_point; // Stores both the stop id and the full
                                  // context at which this value was last
  // updated.  When we are asked to update the value object, we check whether
  // the context & stop id are the same before updating.
  ConstString m_name; // The name of this object
  DataExtractor
      m_data; // A data extractor that can be used to extract the value.
  Value m_value;
  Error m_error; // An error object that can describe any errors that occur when
                 // updating values.
  std::string m_value_str; // Cached value string that will get cleared if/when
                           // the value is updated.
  std::string m_old_value_str; // Cached old value string from the last time the
                               // value was gotten
  std::string m_location_str;  // Cached location string that will get cleared
                               // if/when the value is updated.
  std::string m_summary_str;   // Cached summary string that will get cleared
                               // if/when the value is updated.
  std::string m_object_desc_str; // Cached result of the "object printer".  This
                                 // differs from the summary
  // in that the summary is consed up by us, the object_desc_string is builtin.

  llvm::Optional<std::pair<TypeValidatorResult, std::string>>
      m_validation_result;

  CompilerType m_override_type; // If the type of the value object should be
                                // overridden, the type to impose.

  ValueObjectManager *m_manager; // This object is managed by the root object
                                 // (any ValueObject that gets created
  // without a parent.)  The manager gets passed through all the generations of
  // dependent objects, and will keep the whole cluster of objects alive as long
  // as a shared pointer to any of them has been handed out.  Shared pointers to
  // value objects must always be made with the GetSP method.

  ChildrenManager m_children;
  std::map<ConstString, ValueObject *> m_synthetic_children;

  ValueObject *m_dynamic_value;
  ValueObject *m_synthetic_value;
  ValueObject *m_deref_valobj;

  lldb::ValueObjectSP m_addr_of_valobj_sp; // We have to hold onto a shared
                                           // pointer to this one because it is
                                           // created
  // as an independent ValueObjectConstResult, which isn't managed by us.

  lldb::Format m_format;
  lldb::Format m_last_format;
  uint32_t m_last_format_mgr_revision;
  lldb::TypeSummaryImplSP m_type_summary_sp;
  lldb::TypeFormatImplSP m_type_format_sp;
  lldb::SyntheticChildrenSP m_synthetic_children_sp;
  lldb::TypeValidatorImplSP m_type_validator_sp;
  ProcessModID m_user_id_of_forced_summary;
  AddressType m_address_type_of_ptr_or_ref_children;

  llvm::SmallVector<uint8_t, 16> m_value_checksum;

  lldb::LanguageType m_preferred_display_language;

  uint64_t m_language_flags;

  bool m_value_is_valid : 1, m_value_did_change : 1, m_children_count_valid : 1,
      m_old_value_valid : 1, m_is_deref_of_parent : 1,
      m_is_array_item_for_pointer : 1, m_is_bitfield_for_scalar : 1,
      m_is_child_at_offset : 1, m_is_getting_summary : 1,
      m_did_calculate_complete_objc_class_type : 1,
      m_is_synthetic_children_generated : 1;

  friend class ValueObjectChild;
  friend class ClangExpressionDeclMap; // For GetValue
  friend class ExpressionVariable;     // For SetName
  friend class Target;                 // For SetName
  friend class ValueObjectConstResultImpl;
  friend class ValueObjectSynthetic; // For ClearUserVisibleData

  //------------------------------------------------------------------
  // Constructors and Destructors
  //------------------------------------------------------------------

  // Use the no-argument constructor to make a constant variable object (with no
  // ExecutionContextScope.)

  ValueObject();

  // Use this constructor to create a "root variable object".  The ValueObject
  // will be locked to this context
  // through-out its lifespan.

  ValueObject(ExecutionContextScope *exe_scope,
              AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad);

  // Use this constructor to create a ValueObject owned by another ValueObject.
  // It will inherit the ExecutionContext
  // of its parent.

  ValueObject(ValueObject &parent);

  ValueObjectManager *GetManager() { return m_manager; }

  virtual bool UpdateValue() = 0;

  virtual LazyBool CanUpdateWithInvalidExecutionContext() {
    return eLazyBoolCalculate;
  }

  virtual void CalculateDynamicValue(lldb::DynamicValueType use_dynamic);

  virtual lldb::DynamicValueType GetDynamicValueTypeImpl() {
    return lldb::eNoDynamicValues;
  }

  virtual bool HasDynamicValueTypeInfo() { return false; }

  virtual void CalculateSyntheticValue(bool use_synthetic = true);

  // Should only be called by ValueObject::GetChildAtIndex()
  // Returns a ValueObject managed by this ValueObject's manager.
  virtual ValueObject *CreateChildAtIndex(size_t idx,
                                          bool synthetic_array_member,
                                          int32_t synthetic_index);

  // Should only be called by ValueObject::GetNumChildren()
  virtual size_t CalculateNumChildren(uint32_t max = UINT32_MAX) = 0;

  void SetNumChildren(size_t num_children);

  void SetValueDidChange(bool value_changed);

  void SetValueIsValid(bool valid);

  void ClearUserVisibleData(
      uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings);

  void AddSyntheticChild(const ConstString &key, ValueObject *valobj);

  DataExtractor &GetDataExtractor();

  void ClearDynamicTypeInformation();

  //------------------------------------------------------------------
  // Subclasses must implement the functions below.
  //------------------------------------------------------------------

  virtual CompilerType GetCompilerTypeImpl() = 0;

  const char *GetLocationAsCStringImpl(const Value &value,
                                       const DataExtractor &data);

  virtual lldb_private::Error
  GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
                 uint32_t data_offset, Module *module,
                 bool mask_error_on_zerosize_type = true);

  bool IsChecksumEmpty();

  void SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType);

private:
  virtual CompilerType MaybeCalculateCompleteType();

  lldb::ValueObjectSP GetValueForExpressionPath_Impl(
      llvm::StringRef expression_cstr,
      ExpressionPathScanEndReason *reason_to_stop,
      ExpressionPathEndResultType *final_value_type,
      const GetValueForExpressionPathOptions &options,
      ExpressionPathAftermath *final_task_on_target);

  DISALLOW_COPY_AND_ASSIGN(ValueObject);
};

//------------------------------------------------------------------------------
// A value object manager class that is seeded with the static variable value
// and it vends the user facing value object. If the type is dynamic it can
// vend the dynamic type. If this user type also has a synthetic type associated
// with it, it will vend the synthetic type. The class watches the process' stop
// ID and will update the user type when needed.
//------------------------------------------------------------------------------
class ValueObjectManager {
  // The root value object is the static typed variable object.
  lldb::ValueObjectSP m_root_valobj_sp;
  // The user value object is the value object the user wants to see.
  lldb::ValueObjectSP m_user_valobj_sp;
  lldb::DynamicValueType m_use_dynamic;
  uint32_t m_stop_id; // The stop ID that m_user_valobj_sp is valid for.
  bool m_use_synthetic;

public:
  ValueObjectManager() {}
  
  ValueObjectManager(lldb::ValueObjectSP in_valobj_sp,
                     lldb::DynamicValueType use_dynamic, bool use_synthetic);
  
  bool IsValid() const;
  
  lldb::ValueObjectSP GetRootSP() const { return m_root_valobj_sp; }
  
  // Gets the correct value object from the root object for a given process
  // stop ID. If dynamic values are enabled, or if synthetic children are
  // enabled, the value object that the user wants to see might change while
  // debugging.
  lldb::ValueObjectSP GetSP();
  
  void SetUseDynamic(lldb::DynamicValueType use_dynamic);
  void SetUseSynthetic(bool use_synthetic);
  lldb::DynamicValueType GetUseDynamic() const { return m_use_dynamic; }
  bool GetUseSynthetic() const { return m_use_synthetic; }
  lldb::TargetSP GetTargetSP() const;
  lldb::ProcessSP GetProcessSP() const;
  lldb::ThreadSP GetThreadSP() const;
  lldb::StackFrameSP GetFrameSP() const;
};

} // namespace lldb_private

#endif // liblldb_ValueObject_h_
