text: //===-- 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 <map>
  #include <vector>
  
  // Other libraries and framework includes
  #include "llvm/ADT/Optional.h"
  #include "llvm/ADT/SmallVector.h"
  
  // Project includes
  #include "lldb/lldb-private.h"
  #include "lldb/Core/DataExtractor.h"
  #include "lldb/Core/Error.h"
  #include "lldb/Core/Flags.h"
  #include "lldb/Core/ConstString.h"
  #include "lldb/Core/UserID.h"
  #include "lldb/Core/Value.h"
  #include "lldb/Symbol/ClangASTType.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"
  
  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;
      };
  
      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 ();
      
      virtual ~ValueObject();
      
      ClangASTType
      GetClangType ();
      
      // 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 (ClangASTType *pointee_or_element_clang_type = NULL);
  
      virtual bool
      IsPointerType ();
      
      virtual bool
      IsArrayType ();
      
      virtual bool
      IsScalarType ();
  
      virtual bool
      IsPointerOrReferenceType ();
      
      virtual bool
      IsPossibleDynamicType ();
  
      virtual bool
      IsObjCNil ();
      
      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(const char* expression,
                                const char** first_unparsed = NULL,
                                ExpressionPathScanEndReason* reason_to_stop = NULL,
                                ExpressionPathEndResultType* final_value_type = NULL,
                                const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(),
                                ExpressionPathAftermath* final_task_on_target = NULL);
      
      int
      GetValuesForExpressionPath(const char* expression,
                                 lldb::ValueObjectListSP& list,
                                 const char** first_unparsed = NULL,
                                 ExpressionPathScanEndReason* reason_to_stop = NULL,
                                 ExpressionPathEndResultType* final_value_type = NULL,
                                 const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(),
                                 ExpressionPathAftermath* final_task_on_target = NULL);
      
      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 = NULL);
  
      virtual int64_t
      GetValueAsSigned (int64_t fail_value, bool *success = NULL);
      
      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 = NULL);
      
      lldb::ValueObjectSP
      GetChildAtIndexPath (const std::vector<size_t> &idxs,
                           size_t* index_of_error = NULL);
      
      lldb::ValueObjectSP
      GetChildAtIndexPath (const std::initializer_list< std::pair<size_t, bool> > &idxs,
                           size_t* index_of_error = NULL);
  
      lldb::ValueObjectSP
      GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs,
                           size_t* index_of_error = NULL);
  
      // this will always create the children if necessary
      lldb::ValueObjectSP
      GetChildAtNamePath (const std::initializer_list<ConstString> &names,
                          ConstString* name_of_error = NULL);
      
      lldb::ValueObjectSP
      GetChildAtNamePath (const std::vector<ConstString> &names,
                          ConstString* name_of_error = NULL);
      
      lldb::ValueObjectSP
      GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
                          ConstString* name_of_error = NULL);
      
      lldb::ValueObjectSP
      GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
                          ConstString* name_of_error = NULL);
      
      virtual lldb::ValueObjectSP
      GetChildMemberWithName (const ConstString &name, bool can_create);
  
      virtual size_t
      GetIndexOfChildWithName (const ConstString &name);
  
      size_t
      GetNumChildren ();
  
      const Value &
      GetValue() const;
  
      Value &
      GetValue();
  
      virtual bool
      ResolveValue (Scalar &scalar);
      
      virtual const char *
      GetLocationAsCString ();
  
      const char *
      GetSummaryAsCString ();
      
      bool
      GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
                           std::string& destination);
      
      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 PrintableRepresentationSpecialCases
      {
          ePrintableRepresentationSpecialCasesDisable = 0,
          ePrintableRepresentationSpecialCasesAllow = 1,
          ePrintableRepresentationSpecialCasesOnly = 3
      };
      
      bool
      DumpPrintableRepresentation (Stream& s,
                                   ValueObjectRepresentationStyle val_obj_display = eValueObjectRepresentationStyleSummary,
                                   lldb::Format custom_format = lldb::eFormatInvalid,
                                   PrintableRepresentationSpecialCases special = ePrintableRepresentationSpecialCasesAllow,
                                   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 = NULL);
      
      lldb::addr_t
      GetPointerValue (AddressType *address_type = NULL);
      
      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 ClangASTType& type, bool can_create);
      
      virtual lldb::ValueObjectSP
      GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool can_create);
  
      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 (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 ClangASTType &clang_ast_type);
      
      virtual lldb::ValueObjectSP
      CastPointerType (const char *name,
                       ClangASTType &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;
      }
      
      bool
      IsSyntheticChildrenGenerated ();
      
      void
      SetSyntheticChildrenGenerated (bool b);
      
      virtual SymbolContextScope *
      GetSymbolContextScope();
      
      void
      Dump (Stream &s);
      
      void
      Dump (Stream &s,
            const DumpValueObjectOptions& options);
  
      static lldb::ValueObjectSP
      CreateValueObjectFromExpression (const char* name,
                                       const char* expression,
                                       const ExecutionContext& exe_ctx);
      
      static lldb::ValueObjectSP
      CreateValueObjectFromExpression (const char* name,
                                       const char* expression,
                                       const ExecutionContext& exe_ctx,
                                       const EvaluateExpressionOptions& options);
      
      static lldb::ValueObjectSP
      CreateValueObjectFromAddress (const char* name,
                                    uint64_t address,
                                    const ExecutionContext& exe_ctx,
                                    ClangASTType type);
  
      static lldb::ValueObjectSP
      CreateValueObjectFromData (const char* name,
                                 const DataExtractor& data,
                                 const ExecutionContext& exe_ctx,
                                 ClangASTType 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);
      
      size_t
      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();
          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 bool
      IsRuntimeSupportValue ();
  
  protected:
      typedef ClusterManager<ValueObject> ValueObjectManager;
      
      class ChildrenManager
      {
      public:
          ChildrenManager() :
              m_mutex(Mutex::eMutexTypeRecursive),
              m_children(),
              m_children_count(0)
          {}
          
          bool
          HasChildAtIndex (size_t idx)
          {
              Mutex::Locker locker(m_mutex);
              ChildrenIterator iter = m_children.find(idx);
              ChildrenIterator end = m_children.end();
              return (iter != end);
          }
          
          ValueObject*
          GetChildAtIndex (size_t idx)
          {
              Mutex::Locker locker(m_mutex);
              ChildrenIterator iter = m_children.find(idx);
              ChildrenIterator end = m_children.end();
              if (iter == end)
                  return NULL;
              else
                  return iter->second;
          }
          
          void
          SetChildAtIndex (size_t idx, ValueObject* valobj)
          {
              ChildrenPair pair(idx,valobj); // we do not need to be mutex-protected to make a pair
              Mutex::Locker locker(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)
          {
              Mutex::Locker locker(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;
          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 NULL if this has no parent
      ValueObject  *      m_root;         // The root of the hierarchy for this ValueObject (or NULL 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;
      
      ClangASTType        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;
      
      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 ClangExpressionVariable; // 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 bool
      CanUpdateWithInvalidExecutionContext ()
      {
          return false;
      }
      
      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() = 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 ClangASTType
      GetClangTypeImpl () = 0;
      
      const char *
      GetLocationAsCStringImpl (const Value& value,
                                const DataExtractor& data);
      
      bool
      IsChecksumEmpty ();
      
  private:
      //------------------------------------------------------------------
      // For ValueObject only
      //------------------------------------------------------------------
      
      virtual ClangASTType
      MaybeCalculateCompleteType ();
      
      lldb::ValueObjectSP
      GetValueForExpressionPath_Impl(const char* expression_cstr,
                                     const char** first_unparsed,
                                     ExpressionPathScanEndReason* reason_to_stop,
                                     ExpressionPathEndResultType* final_value_type,
                                     const GetValueForExpressionPathOptions& options,
                                     ExpressionPathAftermath* final_task_on_target);
          
      // this method will ONLY expand [] expressions into a VOList and return
      // the number of elements it added to the VOList
      // it will NOT loop through expanding the follow-up of the expression_cstr
      // for all objects in the list
      int
      ExpandArraySliceExpression(const char* expression_cstr,
                                 const char** first_unparsed,
                                 lldb::ValueObjectSP root,
                                 lldb::ValueObjectListSP& list,
                                 ExpressionPathScanEndReason* reason_to_stop,
                                 ExpressionPathEndResultType* final_value_type,
                                 const GetValueForExpressionPathOptions& options,
                                 ExpressionPathAftermath* final_task_on_target);
                                 
      
      DISALLOW_COPY_AND_ASSIGN (ValueObject);
  
  };
  
  } // namespace lldb_private
  
  #endif  // liblldb_ValueObject_h_
  