//===-- ValueObject.h -------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ValueObject_h_
#define liblldb_ValueObject_h_

#include "lldb/Core/Value.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/SharedCluster.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
#include "lldb/lldb-types.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"

#include <functional>
#include <initializer_list>
#include <map>
#include <mutex>
#include <string>
#include <utility>

#include <stddef.h>
#include <stdint.h>

namespace lldb_private {
class Declaration;
class DumpValueObjectOptions;
class EvaluateExpressionOptions;
class ExecutionContextScope;
class Log;
class Scalar;
class Stream;
class SymbolContextScope;
class TypeFormatImpl;
class TypeSummaryImpl;
class TypeSummaryOptions;

/// 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,
    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, Status &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 Status &GetError();

  ConstString GetName() const;

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

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

  lldb::ValueObjectSP
  GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t, bool>> idxs,
                      size_t *index_of_error = nullptr);

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

  lldb::ValueObjectSP
  GetChildAtNamePath(llvm::ArrayRef<std::pair<ConstString, bool>> names,
                     ConstString *name_of_error = nullptr);

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

  virtual size_t GetIndexOfChildWithName(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(Status &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);

  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); }

  // Change the name of the current ValueObject. Should *not* be used from a
  // synthetic child provider as it would change the name of the non synthetic
  // child as well.
  void SetName(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(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();

  virtual bool IsSynthetic() { return false; }

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

  virtual lldb::ValueObjectSP CreateConstantValue(ConstString name);

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

  // Creates a copy of the ValueObject with a new name and setting the current
  // ValueObject as its parent. It should be used when we want to change the
  // name of a ValueObject without modifying the actual ValueObject itself
  // (e.g. sythetic child provider).
  virtual lldb::ValueObjectSP Clone(ConstString new_name);

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

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

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

  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, Status &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, Status &error);

  virtual bool SetData(DataExtractor &data, Status &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);
  }

  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;
  Status
      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.

  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;
  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(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);

  bool IsChecksumEmpty();

  void SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType);

private:
  virtual CompilerType MaybeCalculateCompleteType();
  void UpdateChildrenAddressType();

  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_
