diff --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py index a80b7ba9ecba..dc3946df5be8 100644 --- a/lldb/examples/synthetic/gnu_libstdcpp.py +++ b/lldb/examples/synthetic/gnu_libstdcpp.py @@ -10,7 +10,6 @@ class StdListSynthProvider: def __init__(self, valobj, dict): self.valobj = valobj - self.update() def next_node(self,node): return node.GetChildMemberWithName('_M_next') @@ -109,7 +108,6 @@ class StdVectorSynthProvider: def __init__(self, valobj, dict): self.valobj = valobj; - self.update() def num_children(self): if self.count == None: @@ -193,7 +191,6 @@ class StdMapSynthProvider: def __init__(self, valobj, dict): self.valobj = valobj; - self.update() # we need this function as a temporary workaround for rdar://problem/10801549 # which prevents us from extracting the std::pair SBType out of the template diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py index 5e405df451a6..ed6928ec7d18 100644 --- a/lldb/examples/synthetic/libcxx.py +++ b/lldb/examples/synthetic/libcxx.py @@ -56,7 +56,6 @@ class stdvector_SynthProvider: def __init__(self, valobj, dict): self.valobj = valobj; - self.update() def num_children(self): try: @@ -114,6 +113,7 @@ class stdvector_SynthProvider: except: pass +# Just an example: the actual summary is produced by a summary string: size=${svar%#} def stdvector_SummaryProvider(valobj,dict): prov = stdvector_SynthProvider(valobj,None) return 'size=' + str(prov.num_children()) @@ -180,7 +180,6 @@ class stdlist_iterator: class stdlist_SynthProvider: def __init__(self, valobj, dict): self.valobj = valobj - self.update() def next_node(self,node): return node.GetChildMemberWithName('__next_') @@ -272,6 +271,7 @@ class stdlist_SynthProvider: except: pass +# Just an example: the actual summary is produced by a summary string: size=${svar%#} def stdlist_SummaryProvider(valobj,dict): prov = stdlist_SynthProvider(valobj,None) return 'size=' + str(prov.num_children()) @@ -368,7 +368,6 @@ class stdmap_SynthProvider: def __init__(self, valobj, dict): self.valobj = valobj; self.pointer_size = self.valobj.GetProcess().GetAddressByteSize() - self.update() def update(self): try: @@ -462,6 +461,7 @@ class stdmap_SynthProvider: print err return None +# Just an example: the actual summary is produced by a summary string: size=${svar%#} def stdmap_SummaryProvider(valobj,dict): prov = stdmap_SynthProvider(valobj,None) return 'size=' + str(prov.num_children()) diff --git a/lldb/include/lldb/Core/FormatClasses.h b/lldb/include/lldb/Core/FormatClasses.h index 527462dbf55d..84f0b2a207b4 100644 --- a/lldb/include/lldb/Core/FormatClasses.h +++ b/lldb/include/lldb/Core/FormatClasses.h @@ -217,16 +217,19 @@ protected: Flags m_flags; lldb::Format m_format; uint32_t m_my_revision; -}; +private: + DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl); +}; + class SyntheticChildrenFrontEnd { protected: - lldb::ValueObjectSP m_backend; + ValueObject &m_backend; public: - SyntheticChildrenFrontEnd(lldb::ValueObjectSP be) : - m_backend(be) + SyntheticChildrenFrontEnd(ValueObject &backend) : + m_backend(backend) {} virtual @@ -243,13 +246,21 @@ public: virtual uint32_t GetIndexOfChildWithName (const ConstString &name) = 0; - virtual void + // this function is assumed to always succeed and it if fails, the front-end should know to deal + // with it in the correct way (most probably, by refusing to return any children) + // the return value of Update() should actually be interpreted as "ValueObjectSyntheticFilter cache is good/bad" + // if =true, ValueObjectSyntheticFilter is allowed to use the children it fetched previously and cached + // if =false, ValueObjectSyntheticFilter must throw away its cache, and query again for children + virtual bool Update() = 0; typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; - -}; + typedef std::auto_ptr AutoPointer; +private: + DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd); +}; + class SyntheticChildren { public: @@ -419,8 +430,8 @@ public: virtual std::string GetDescription () = 0; - virtual SyntheticChildrenFrontEnd::SharedPointer - GetFrontEnd (lldb::ValueObjectSP backend) = 0; + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd (ValueObject &backend) = 0; typedef STD_SHARED_PTR(SyntheticChildren) SharedPointer; typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&); @@ -434,6 +445,9 @@ public: protected: uint32_t m_my_revision; Flags m_flags; + +private: + DISALLOW_COPY_AND_ASSIGN(SyntheticChildren); }; class TypeFilterImpl : public SyntheticChildren @@ -525,8 +539,8 @@ public: public: FrontEnd(TypeFilterImpl* flt, - lldb::ValueObjectSP be) : - SyntheticChildrenFrontEnd(be), + ValueObject &backend) : + SyntheticChildrenFrontEnd(backend), filter(flt) {} @@ -546,11 +560,11 @@ public: { if (idx >= filter->GetCount()) return lldb::ValueObjectSP(); - return m_backend->GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), can_create); + return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), can_create); } - virtual void - Update() {} + virtual bool + Update() { return false; } virtual uint32_t GetIndexOfChildWithName (const ConstString &name) @@ -567,14 +581,18 @@ public: typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; + private: + DISALLOW_COPY_AND_ASSIGN(FrontEnd); }; - virtual SyntheticChildrenFrontEnd::SharedPointer - GetFrontEnd(lldb::ValueObjectSP backend) + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) { - return SyntheticChildrenFrontEnd::SharedPointer(new FrontEnd(this, backend)); + return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); } +private: + DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl); }; #ifndef LLDB_DISABLE_PYTHON @@ -641,7 +659,7 @@ public: public: FrontEnd(std::string pclass, - lldb::ValueObjectSP be); + ValueObject &backend); virtual ~FrontEnd(); @@ -657,13 +675,13 @@ public: virtual lldb::ValueObjectSP GetChildAtIndex (uint32_t idx, bool can_create); - virtual void + virtual bool Update() { if (!m_wrapper_sp || m_interpreter == NULL) - return; + return false; - m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); + return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); } virtual uint32_t @@ -675,14 +693,19 @@ public: } typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; - + + private: + DISALLOW_COPY_AND_ASSIGN(FrontEnd); }; - virtual SyntheticChildrenFrontEnd::SharedPointer - GetFrontEnd(lldb::ValueObjectSP backend) + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) { - return SyntheticChildrenFrontEnd::SharedPointer(new FrontEnd(m_python_class, backend)); + return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); } + +private: + DISALLOW_COPY_AND_ASSIGN(TypeSyntheticImpl); }; #endif // #ifndef LLDB_DISABLE_PYTHON @@ -841,8 +864,8 @@ public: public: FrontEnd(SyntheticArrayView* flt, - lldb::ValueObjectSP be) : - SyntheticChildrenFrontEnd(be), + ValueObject &backend) : + SyntheticChildrenFrontEnd(backend), filter(flt) {} @@ -862,28 +885,32 @@ public: { if (idx >= filter->GetCount()) return lldb::ValueObjectSP(); - return m_backend->GetSyntheticArrayMember(filter->GetRealIndexForIndex(idx), can_create); + return m_backend.GetSyntheticArrayMember(filter->GetRealIndexForIndex(idx), can_create); } - virtual void - Update() {} + virtual bool + Update() { return false; } virtual uint32_t GetIndexOfChildWithName (const ConstString &name_cs); typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; - + + private: + DISALLOW_COPY_AND_ASSIGN(FrontEnd); }; - virtual SyntheticChildrenFrontEnd::SharedPointer - GetFrontEnd(lldb::ValueObjectSP backend) + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) { - return SyntheticChildrenFrontEnd::SharedPointer(new FrontEnd(this, backend)); + return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); } private: SyntheticArrayRange m_head; SyntheticArrayRange *m_tail; - + +private: + DISALLOW_COPY_AND_ASSIGN(SyntheticArrayView); }; @@ -1158,8 +1185,11 @@ public: { } + // we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for + // extended periods of time and we trust the ValueObject to stay around for as long as it is required + // for us to generate its summary virtual bool - FormatObject (lldb::ValueObjectSP object, + FormatObject (ValueObject *valobj, std::string& dest) = 0; virtual std::string @@ -1181,7 +1211,9 @@ public: protected: uint32_t m_my_revision; Flags m_flags; - + +private: + DISALLOW_COPY_AND_ASSIGN(TypeSummaryImpl); }; // simple string-based summaries, using ${var to show data @@ -1213,7 +1245,7 @@ struct StringSummaryFormat : public TypeSummaryImpl } virtual bool - FormatObject(lldb::ValueObjectSP object, + FormatObject(ValueObject *valobj, std::string& dest); virtual std::string @@ -1224,7 +1256,10 @@ struct StringSummaryFormat : public TypeSummaryImpl { return false; } - + + +private: + DISALLOW_COPY_AND_ASSIGN(StringSummaryFormat); }; #ifndef LLDB_DISABLE_PYTHON @@ -1277,7 +1312,7 @@ struct ScriptSummaryFormat : public TypeSummaryImpl } virtual bool - FormatObject(lldb::ValueObjectSP object, + FormatObject(ValueObject *valobj, std::string& dest); virtual std::string @@ -1291,6 +1326,9 @@ struct ScriptSummaryFormat : public TypeSummaryImpl typedef STD_SHARED_PTR(ScriptSummaryFormat) SharedPointer; + +private: + DISALLOW_COPY_AND_ASSIGN(ScriptSummaryFormat); }; #endif // #ifndef LLDB_DISABLE_PYTHON @@ -1317,7 +1355,7 @@ public: } // if constructing with a given type, is_regex cannot be true since we are - // very clearly pap + // giving an exact type to match TypeNameSpecifierImpl (lldb::TypeSP type) : m_is_regex(false), m_type() @@ -1381,6 +1419,10 @@ private: lldb::TypeImplSP m_typeimpl_sp; }; TypeOrName m_type; + + +private: + DISALLOW_COPY_AND_ASSIGN(TypeNameSpecifierImpl); }; } // namespace lldb_private diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index bbddf10a283a..0943cf11fed4 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -69,54 +69,67 @@ public: enum GetExpressionPathFormat { - eDereferencePointers = 1, - eHonorPointers + eGetExpressionPathFormatDereferencePointers = 1, + eGetExpressionPathFormatHonorPointers }; enum ValueObjectRepresentationStyle { - eDisplayValue = 1, - eDisplaySummary, - eDisplayLanguageSpecific, - eDisplayLocation, - eDisplayChildrenCount, - eDisplayType + eValueObjectRepresentationStyleValue = 1, + eValueObjectRepresentationStyleSummary, + eValueObjectRepresentationStyleLanguageSpecific, + eValueObjectRepresentationStyleLocation, + eValueObjectRepresentationStyleChildrenCount, + eValueObjectRepresentationStyleType }; enum ExpressionPathScanEndReason { - eEndOfString = 1, // out of data to parse - eNoSuchChild, // child element not found - eEmptyRangeNotAllowed, // [] only allowed for arrays - eDotInsteadOfArrow, // . used when -> should be used - eArrowInsteadOfDot, // -> used when . should be used - eFragileIVarNotAllowed, // ObjC ivar expansion not allowed - eRangeOperatorNotAllowed, // [] not allowed by options - eRangeOperatorInvalid, // [] not valid on objects other than scalars, pointers or arrays - eArrayRangeOperatorMet, // [] is good for arrays, but I cannot parse it - eBitfieldRangeOperatorMet, // [] is good for bitfields, but I cannot parse after it - eUnexpectedSymbol, // something is malformed in the expression - eTakingAddressFailed, // impossible to apply & operator - eDereferencingFailed, // impossible to apply * operator - eRangeOperatorExpanded, // [] was expanded into a VOList - eUnknown = 0xFFFF + eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse + eExpressionPathScanEndReasonNoSuchChild, // 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 { - ePlain = 1, // anything but... - eBitfield, // a bitfield - eBoundedRange, // a range [low-high] - eUnboundedRange, // a range [] - eValueObjectList, // several items in a VOList - eInvalid = 0xFFFF + 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 { - eNothing = 1, // just return it - eDereference, // dereference the target - eTakeAddress // take target's address + 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 @@ -211,7 +224,7 @@ public: bool m_show_location; bool m_use_objc; lldb::DynamicValueType m_use_dynamic; - lldb::SyntheticValueType m_use_synthetic; + bool m_use_synthetic; bool m_scope_already_checked; bool m_flat_output; uint32_t m_omit_summary_depth; @@ -227,7 +240,7 @@ public: m_show_location(false), m_use_objc(false), m_use_dynamic(lldb::eNoDynamicValues), - m_use_synthetic(lldb::eUseSyntheticFilter), + m_use_synthetic(true), m_scope_already_checked(false), m_flat_output(false), m_omit_summary_depth(0), @@ -305,9 +318,9 @@ public: } DumpValueObjectOptions& - SetUseSyntheticValue(lldb::SyntheticValueType syn = lldb::eUseSyntheticFilter) + SetUseSyntheticValue(bool use_synthetic = true) { - m_use_synthetic = syn; + m_use_synthetic = use_synthetic; return *this; } @@ -344,13 +357,13 @@ public: { if (raw) { - SetUseSyntheticValue(lldb::eNoSyntheticFilter); + SetUseSyntheticValue(false); SetOmitSummaryDepth(UINT32_MAX); SetIgnoreCap(true); } else { - SetUseSyntheticValue(lldb::eUseSyntheticFilter); + SetUseSyntheticValue(true); SetOmitSummaryDepth(0); SetIgnoreCap(false); } @@ -599,7 +612,7 @@ public: GetBaseClassPath (Stream &s); virtual void - GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat = eDereferencePointers); + GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers); lldb::ValueObjectSP GetValueForExpressionPath(const char* expression, @@ -725,19 +738,21 @@ public: GetObjectDescription (); bool - GetPrintableRepresentation(Stream& s, - ValueObjectRepresentationStyle val_obj_display = eDisplaySummary, - lldb::Format custom_format = lldb::eFormatInvalid); - - bool - HasSpecialCasesForPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display, - lldb::Format custom_format); + 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 = eDisplaySummary, - lldb::Format custom_format = lldb::eFormatInvalid, - bool only_special = false); + DumpPrintableRepresentation (Stream& s, + ValueObjectRepresentationStyle val_obj_display = eValueObjectRepresentationStyleSummary, + lldb::Format custom_format = lldb::eFormatInvalid, + PrintableRepresentationSpecialCases special = ePrintableRepresentationSpecialCasesAllow); bool GetValueIsValid () const; @@ -800,11 +815,14 @@ public: GetStaticValue (); lldb::ValueObjectSP - GetSyntheticValue (lldb::SyntheticValueType use_synthetic); + GetSyntheticValue (bool use_synthetic = true); virtual bool HasSyntheticValue(); + virtual bool + IsSynthetic() { return false; } + virtual lldb::ValueObjectSP CreateConstantValue (const ConstString &name); @@ -842,9 +860,9 @@ public: virtual void ValueUpdated () { - m_value_str.clear(); - m_summary_str.clear(); - m_object_desc_str.clear(); + ClearUserVisibleData(eClearUserVisibleDataItemsValue | + eClearUserVisibleDataItemsSummary | + eClearUserVisibleDataItemsDescription); } virtual bool @@ -909,7 +927,7 @@ public: SetFormat (lldb::Format format) { if (format != m_format) - m_value_str.clear(); + ClearUserVisibleData(eClearUserVisibleDataItemsValue); m_format = format; } @@ -924,7 +942,7 @@ public: SetSummaryFormat(lldb::TypeSummaryImplSP format) { m_type_summary_sp = format; - m_summary_str.clear(); + ClearUserVisibleData(eClearUserVisibleDataItemsSummary); m_is_getting_summary = false; } @@ -932,7 +950,7 @@ public: SetValueFormat(lldb::TypeFormatImplSP format) { m_type_format_sp = format; - m_value_str.clear(); + ClearUserVisibleData(eClearUserVisibleDataItemsValue); } lldb::TypeFormatImplSP @@ -943,10 +961,12 @@ public: } void - SetSyntheticChildren(lldb::SyntheticChildrenSP synth) + SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) { - m_synthetic_children_sp = synth; - m_synthetic_value = NULL; + if (synth_sp.get() == m_synthetic_children_sp.get()) + return; + ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren); + m_synthetic_children_sp = synth_sp; } lldb::SyntheticChildrenSP @@ -1155,7 +1175,7 @@ protected: CalculateDynamicValue (lldb::DynamicValueType use_dynamic); virtual void - CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic); + CalculateSyntheticValue (bool use_synthetic = true); // Should only be called by ValueObject::GetChildAtIndex() // Returns a ValueObject managed by this ValueObject's manager. @@ -1176,7 +1196,7 @@ protected: SetValueIsValid (bool valid); void - ClearUserVisibleData(); + ClearUserVisibleData(uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings); void AddSyntheticChild (const ConstString &key, diff --git a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h index 1ef6e4db159b..247c5f5c79e6 100644 --- a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -13,7 +13,6 @@ // C Includes // C++ Includes #include -#include #include // Other libraries and framework includes // Project includes @@ -61,13 +60,15 @@ public: virtual bool HasSyntheticValue() { - return true; // we are our own synthetic value + return false; } + virtual bool + IsSynthetic() { return true; } + virtual void - CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic) + CalculateSyntheticValue (bool use_synthetic) { - m_synthetic_value = this; } virtual bool @@ -96,16 +97,6 @@ public: else return NULL; } - - void - SetOwningSP (lldb::ValueObjectSP &owning_sp) - { - if (m_owning_valobj_sp == owning_sp) - return; - - assert (m_owning_valobj_sp.get() == NULL); - m_owning_valobj_sp = owning_sp; - } protected: virtual bool @@ -117,21 +108,19 @@ protected: virtual lldb::clang_type_t GetClangTypeImpl (); - Address m_address; ///< The variable that this value object is based upon - lldb::TypeSP m_type_sp; - lldb::ValueObjectSP m_owning_valobj_sp; - lldb::SyntheticValueType m_use_synthetic; - lldb::SyntheticChildrenSP m_synth_sp; // hold on to your synthetic children provider - lldb::SyntheticChildrenFrontEndSP m_synth_filter; + // we need to hold on to the SyntheticChildren because someone might delete the type binding while we are alive + lldb::SyntheticChildrenSP m_synth_sp; + std::auto_ptr m_synth_filter_ap; - typedef std::map ByIndexMap; + typedef std::map ByIndexMap; typedef std::map NameToIndexMap; typedef ByIndexMap::iterator ByIndexIterator; typedef NameToIndexMap::iterator NameToIndexIterator; - - ByIndexMap m_children_byindex; - NameToIndexMap m_name_toindex; + + ByIndexMap m_children_byindex; + NameToIndexMap m_name_toindex; + uint32_t m_children_count; private: friend class ValueObject; diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 4015f91c5100..e5a787cdb0d3 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -82,7 +82,7 @@ public: typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data); - typedef void (*SWIGPythonUpdateSynthProviderInstance) (void* data); + typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data); typedef bool (*SWIGPythonCallCommand) (const char *python_function_name, const char *session_dictionary_name, @@ -229,9 +229,10 @@ public: return UINT32_MAX; } - virtual void + virtual bool UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) { + return false; } virtual bool diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index f51fa428b545..b254046b3b22 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -84,7 +84,7 @@ public: virtual int GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor, const char* child_name); - virtual void + virtual bool UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor); virtual bool diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 9c3a8c2e4878..6960cacb408d 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -336,12 +336,6 @@ namespace lldb { eDynamicDontRunTarget = 2 } DynamicValueType; - typedef enum SyntheticValueType - { - eNoSyntheticFilter = false, - eUseSyntheticFilter = true - } SyntheticValueType; - typedef enum AccessType { eAccessNone, diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig index 3277e780e26a..1442608d6bb4 100644 --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -258,7 +258,7 @@ LLDBSwigPythonCreateSyntheticProvider // has ownership of it and will manage memory for this object by itself lldb::SBValue *valobj_sb = new lldb::SBValue(valobj_sp); - PyObject *ValObj_PyObj = SWIG_NewPointerObj((void *)valobj_sb, SWIGTYPE_p_lldb__SBValue, SWIG_POINTER_OWN); + PyObject *ValObj_PyObj = SWIG_NewPointerObj((void *)valobj_sb, SWIGTYPE_p_lldb__SBValue, 0); if (ValObj_PyObj == NULL) Py_RETURN_NONE; @@ -456,16 +456,19 @@ LLDBSwigPython_GetIndexOfChildWithName return 0; } -SWIGEXPORT void +SWIGEXPORT bool LLDBSwigPython_UpdateSynthProviderInstance ( PyObject *implementor ) { + + bool ret_val = false; + static char callee_name[] = "update"; if (implementor == NULL || implementor == Py_None) - return; + return ret_val; // all this code is here because update is optional, so we don't want to bother trying to call it unless it's been def:ined for us // other synth provider calls are mandatory, so we want to fail in a very obvious way if they are missing! @@ -479,7 +482,7 @@ LLDBSwigPython_UpdateSynthProviderInstance if (pmeth == NULL || pmeth == Py_None) { Py_XDECREF(pmeth); - return; + return ret_val; } if (PyCallable_Check(pmeth) == 0) @@ -490,7 +493,7 @@ LLDBSwigPython_UpdateSynthProviderInstance } Py_XDECREF(pmeth); - return; + return ret_val; } if (PyErr_Occurred()) @@ -509,8 +512,13 @@ LLDBSwigPython_UpdateSynthProviderInstance PyErr_Print(); PyErr_Clear(); } + + if (py_return == Py_True) + ret_val = true; Py_XDECREF(py_return); + + return ret_val; } diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index b8c3c92f438d..f039310212a9 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -363,7 +363,7 @@ CommandObjectExpression::EvaluateExpression .SetUseDynamicType(use_dynamic) .SetScopeChecked(true) .SetFlatOutput(false) - .SetUseSyntheticValue(lldb::eUseSyntheticFilter) + .SetUseSyntheticValue(true) .SetOmitSummaryDepth(0) .SetIgnoreCap(false) .SetFormat(format) diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index a57a835de871..b59cd633058c 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -414,7 +414,7 @@ public: .SetShowLocation(m_varobj_options.show_location) .SetUseObjectiveC(m_varobj_options.use_objc) .SetUseDynamicType(m_varobj_options.use_dynamic) - .SetUseSyntheticValue((lldb::SyntheticValueType)m_varobj_options.use_synth) + .SetUseSyntheticValue(m_varobj_options.use_synth) .SetFlatOutput(m_varobj_options.flat_output) .SetOmitSummaryDepth(m_varobj_options.no_summary_depth) .SetIgnoreCap(m_varobj_options.ignore_cap) diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index e47d15da2403..30c5d946eac4 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -701,7 +701,7 @@ public: .SetUseObjectiveC(m_varobj_options.use_objc) .SetScopeChecked(scope_already_checked) .SetFlatOutput(m_varobj_options.flat_output) - .SetUseSyntheticValue(m_varobj_options.be_raw ? lldb::eNoSyntheticFilter : (m_varobj_options.use_synth ? lldb::eUseSyntheticFilter : lldb::eNoSyntheticFilter) ) + .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth) .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth) .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap) .SetFormat(format) diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index a6d8262adc16..890a60102f91 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -600,7 +600,7 @@ public: .SetShowLocation(m_varobj_options.show_location) .SetUseObjectiveC(m_varobj_options.use_objc) .SetUseDynamicType(m_varobj_options.use_dynamic) - .SetUseSyntheticValue((lldb::SyntheticValueType)m_varobj_options.use_synth) + .SetUseSyntheticValue(m_varobj_options.use_synth) .SetFlatOutput(m_varobj_options.flat_output) .SetOmitSummaryDepth(m_varobj_options.no_summary_depth) .SetIgnoreCap(m_varobj_options.ignore_cap); diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 3aff807b4ee5..6b93aa971a07 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -867,20 +867,20 @@ ScanFormatDescriptor (const char* var_name_begin, log->Printf("%s is an unknown format", format_name); // if this is an @ sign, print ObjC description if (*format_name == '@') - *val_obj_display = ValueObject::eDisplayLanguageSpecific; + *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; // if this is a V, print the value using the default format else if (*format_name == 'V') - *val_obj_display = ValueObject::eDisplayValue; + *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; // if this is an L, print the location of the value else if (*format_name == 'L') - *val_obj_display = ValueObject::eDisplayLocation; + *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; // if this is an S, print the summary after all else if (*format_name == 'S') - *val_obj_display = ValueObject::eDisplaySummary; + *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; else if (*format_name == '#') - *val_obj_display = ValueObject::eDisplayChildrenCount; + *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; else if (*format_name == 'T') - *val_obj_display = ValueObject::eDisplayType; + *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; else if (log) log->Printf("%s is an error, leaving the previous value alone", format_name); } @@ -889,7 +889,7 @@ ScanFormatDescriptor (const char* var_name_begin, { if (log) log->Printf("will display value for this VO"); - *val_obj_display = ValueObject::eDisplayValue; + *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; } delete format_name; } @@ -989,7 +989,7 @@ ExpandExpressionPath (ValueObject* valobj, *do_deref_pointer = true; } - valobj->GetExpressionPath(sstring, true, ValueObject::eHonorPointers); + valobj->GetExpressionPath(sstring, true, ValueObject::eGetExpressionPathFormatHonorPointers); if (log) log->Printf("expression path to expand in phase 0: %s",sstring.GetData()); sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3); @@ -1020,7 +1020,7 @@ ExpandIndexedExpression (ValueObject* valobj, ValueObject::GetValueForExpressionPathOptions options; ValueObject::ExpressionPathEndResultType final_value_type; ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eDereference : ValueObject::eNothing); + ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.get(), &first_unparsed, &reason_to_stop, @@ -1135,8 +1135,8 @@ Debugger::FormatPrompt const RegisterInfo *reg_info = NULL; RegisterContext *reg_ctx = NULL; bool do_deref_pointer = false; - ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eEndOfString; - ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::ePlain; + ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; + ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; // Each variable must set success to true below... bool var_success = false; @@ -1164,7 +1164,9 @@ Debugger::FormatPrompt if (*var_name_begin == 's') { - valobj = valobj->GetSyntheticValue(eUseSyntheticFilter).get(); + valobj = valobj->GetSyntheticValue().get(); + if (!valobj) + break; var_name_begin++; } @@ -1179,10 +1181,10 @@ Debugger::FormatPrompt log->Printf("initial string: %s",var_name_begin); ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? - ValueObject::eDereference : ValueObject::eNothing); + ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); ValueObject::GetValueForExpressionPathOptions options; options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); - ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary; + ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; ValueObject* target = NULL; Format custom_format = eFormatInvalid; const char* var_name_final = NULL; @@ -1201,7 +1203,7 @@ Debugger::FormatPrompt { was_plain_var = true; target = valobj; - val_obj_display = ValueObject::eDisplayValue; + val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; } else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) { @@ -1209,7 +1211,7 @@ Debugger::FormatPrompt // this is a variable with some custom format applied to it const char* percent_position; target = valobj; - val_obj_display = ValueObject::eDisplayValue; + val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; ScanFormatDescriptor (var_name_begin, var_name_end, &var_name_final, @@ -1276,10 +1278,10 @@ Debugger::FormatPrompt else break; - is_array_range = (final_value_type == ValueObject::eBoundedRange || - final_value_type == ValueObject::eUnboundedRange); + is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || + final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); - do_deref_pointer = (what_next == ValueObject::eDereference); + do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); if (do_deref_pointer && !is_array_range) { @@ -1302,14 +1304,14 @@ Debugger::FormatPrompt bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); bool is_aggregate = ClangASTContext::IsAggregateType(target->GetClangType()); - if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eDisplayValue) // this should be wrong, but there are some exceptions + if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions { StreamString str_temp; if (log) log->Printf("I am into array || pointer && !range"); - if (target->HasSpecialCasesForPrintableRepresentation(val_obj_display, - custom_format)) + if (target->HasSpecialPrintableRepresentation(val_obj_display, + custom_format)) { // try to use the special cases var_success = target->DumpPrintableRepresentation(str_temp, @@ -1334,9 +1336,10 @@ Debugger::FormatPrompt } else if (is_pointer) // if pointer, value is the address stored { - var_success = target->GetPrintableRepresentation(s, + var_success = target->DumpPrintableRepresentation(s, val_obj_display, - custom_format); + custom_format, + ValueObject::ePrintableRepresentationSpecialCasesDisable); } else { @@ -1357,7 +1360,7 @@ Debugger::FormatPrompt } // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it - if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eDisplayValue))) + if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) { s << ""; var_success = true; diff --git a/lldb/source/Core/FormatClasses.cpp b/lldb/source/Core/FormatClasses.cpp index d3a23d102190..fab31ddd9a0c 100644 --- a/lldb/source/Core/FormatClasses.cpp +++ b/lldb/source/Core/FormatClasses.cpp @@ -22,7 +22,6 @@ #include "lldb/Core/FormatClasses.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" -#include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Target/StackFrame.h" @@ -66,17 +65,17 @@ StringSummaryFormat::StringSummaryFormat(const TypeSummaryImpl::Flags& flags, } bool -StringSummaryFormat::FormatObject(lldb::ValueObjectSP object, +StringSummaryFormat::FormatObject(ValueObject *valobj, std::string& retval) { - if (!object.get()) + if (!valobj) { - retval.assign("NULL sp"); + retval.assign("NULL ValueObject"); return false; } StreamString s; - ExecutionContext exe_ctx (object->GetExecutionContextRef()); + ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); SymbolContext sc; StackFrame *frame = exe_ctx.GetFramePtr(); if (frame) @@ -84,15 +83,22 @@ StringSummaryFormat::FormatObject(lldb::ValueObjectSP object, if (IsOneliner()) { - ValueObjectSP synth_valobj = object->GetSyntheticValue(lldb::eUseSyntheticFilter); - const uint32_t num_children = synth_valobj->GetNumChildren(); + ValueObject* object; + + ValueObjectSP synth_valobj = valobj->GetSyntheticValue(); + if (synth_valobj) + object = synth_valobj.get(); + else + object = valobj; + + const uint32_t num_children = object->GetNumChildren(); if (num_children) { s.PutChar('('); for (uint32_t idx=0; idxGetChildAtIndex(idx, true)); + lldb::ValueObjectSP child_sp(object->GetChildAtIndex(idx, true)); if (child_sp.get()) { if (idx) @@ -100,9 +106,12 @@ StringSummaryFormat::FormatObject(lldb::ValueObjectSP object, if (!HideNames()) { s.PutCString(child_sp.get()->GetName().AsCString()); - s.PutChar('='); + s.PutCString(" = "); } - child_sp.get()->GetPrintableRepresentation(s); + child_sp.get()->DumpPrintableRepresentation(s, + ValueObject::eValueObjectRepresentationStyleSummary, + lldb::eFormatInvalid, + ValueObject::ePrintableRepresentationSpecialCasesDisable); } } @@ -120,7 +129,7 @@ StringSummaryFormat::FormatObject(lldb::ValueObjectSP object, } else { - if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get())) + if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, valobj)) { retval.assign(s.GetString()); return true; @@ -167,14 +176,21 @@ ScriptSummaryFormat::ScriptSummaryFormat(const TypeSummaryImpl::Flags& flags, } bool -ScriptSummaryFormat::FormatObject(lldb::ValueObjectSP object, +ScriptSummaryFormat::FormatObject(ValueObject *valobj, std::string& retval) { Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - Debugger& dbg = object->GetTargetSP()->GetDebugger(); - ScriptInterpreter *script_interpreter = dbg.GetCommandInterpreter().GetScriptInterpreter(); - + TargetSP target_sp(valobj->GetTargetSP()); + + if (!target_sp) + { + retval.assign("error: no target"); + return false; + } + + ScriptInterpreter *script_interpreter = target_sp->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (!script_interpreter) { retval.assign("error: no ScriptInterpreter"); @@ -182,7 +198,7 @@ ScriptSummaryFormat::FormatObject(lldb::ValueObjectSP object, } return script_interpreter->GetScriptedSummary(m_function_name.c_str(), - object, + valobj->GetSP(), m_script_function_sp, retval); @@ -253,19 +269,24 @@ SyntheticArrayView::GetDescription() #ifndef LLDB_DISABLE_PYTHON -TypeSyntheticImpl::FrontEnd::FrontEnd(std::string pclass, lldb::ValueObjectSP be) : - SyntheticChildrenFrontEnd(be), +TypeSyntheticImpl::FrontEnd::FrontEnd(std::string pclass, ValueObject &backend) : + SyntheticChildrenFrontEnd(backend), m_python_class(pclass), m_wrapper_sp(), m_interpreter(NULL) { - if (be.get() == NULL) + if (backend == NULL) return; - m_interpreter = m_backend->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + TargetSP target_sp = backend.GetTargetSP(); + + if (!target_sp) + return; + + m_interpreter = target_sp->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); if (m_interpreter != NULL) - m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider(m_python_class, m_backend); + m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider(m_python_class, backend.GetSP()); } TypeSyntheticImpl::FrontEnd::~FrontEnd() diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 1423936cf467..b2f3e3f7fbb1 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -693,15 +693,12 @@ FormatManager::LoadLibcxxFormatters() "libcxx.stdmap_SynthProvider"))); stl_summary_flags.SetDontShowChildren(false); - code.assign(" libcxx.stdvector_SummaryProvider(valobj,dict)"); libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)vector<.+>$")), - TypeSummaryImplSP(new ScriptSummaryFormat(stl_summary_flags, "libcxx.stdvector_SummaryProvider",code.c_str()))); - code.assign(" libcxx.stdlist_SummaryProvider(valobj,dict)"); + TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)list<.+>$")), - TypeSummaryImplSP(new ScriptSummaryFormat(stl_summary_flags, "libcxx.stdlist_SummaryProvider",code.c_str()))); - code.assign(" libcxx.stdmap_SummaryProvider(valobj,dict)"); + TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)map<.+> >$")), - TypeSummaryImplSP(new ScriptSummaryFormat(stl_summary_flags, "libcxx.stdmap_SummaryProvider",code.c_str()))); + TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); #endif } diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 1a7e3702b83a..4ec7088c780a 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -179,7 +179,7 @@ ValueObject::UpdateValueIfNeeded (DynamicValueType use_dynamic, bool update_form // because of the frozen-pointer depth limit) // TODO: decouple summary from value and then remove this code and only force-clear the summary if (update_format && !did_change_formats) - m_summary_str.clear(); + ClearUserVisibleData(eClearUserVisibleDataItemsSummary); return m_error.Success(); } @@ -199,7 +199,7 @@ ValueObject::UpdateValueIfNeeded (DynamicValueType use_dynamic, bool update_form { m_old_value_valid = true; m_old_value_str.swap (m_value_str); - m_value_str.clear(); + ClearUserVisibleData(eClearUserVisibleDataItemsValue); } ClearUserVisibleData(); @@ -268,7 +268,7 @@ ValueObject::SetNeedsUpdate () m_update_point.SetNeedsUpdate(); // We have to clear the value string here so ConstResult children will notice if their values are // changed by hand (i.e. with SetValueAsCString). - m_value_str.clear(); + ClearUserVisibleData(eClearUserVisibleDataItemsValue); } ClangASTType @@ -671,7 +671,9 @@ ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, { if (summary_ptr) { - summary_ptr->FormatObject(GetSP(), destination); + if (HasSyntheticValue()) + m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#}) + summary_ptr->FormatObject(this, destination); } else { @@ -1242,110 +1244,18 @@ ValueObject::GetValueAsUnsigned (uint64_t fail_value) return fail_value; } -bool -ValueObject::GetPrintableRepresentation(Stream& s, - ValueObjectRepresentationStyle val_obj_display, - Format custom_format) -{ - - if (custom_format != eFormatInvalid) - SetFormat(custom_format); - - const char * return_value; - std::string alloc_mem; - - switch(val_obj_display) - { - case eDisplayValue: - return_value = GetValueAsCString(); - break; - - case eDisplaySummary: - return_value = GetSummaryAsCString(); - break; - - case eDisplayLanguageSpecific: - return_value = GetObjectDescription(); - break; - - case eDisplayLocation: - return_value = GetLocationAsCString(); - break; - - case eDisplayChildrenCount: - { - alloc_mem.resize(512); - return_value = &alloc_mem[0]; - int count = GetNumChildren(); - snprintf((char*)return_value, 512, "%d", count); - } - break; - - case eDisplayType: - return_value = GetTypeName().AsCString(); - break; - - default: - break; - } - - if (!return_value) - { - if (val_obj_display == eDisplayValue) - return_value = GetSummaryAsCString(); - else if (val_obj_display == eDisplaySummary) - { - if (ClangASTContext::IsAggregateType (GetClangType()) == true) - { - // this thing has no value, and it seems to have no summary - // some combination of unitialized data and other factors can also - // raise this condition, so let's print a nice generic description - { - alloc_mem.resize(684); - return_value = &alloc_mem[0]; - snprintf((char*)return_value, 684, "%s @ %s", GetTypeName().AsCString(), GetLocationAsCString()); - } - } - else - return_value = GetValueAsCString(); - } - } - - if (return_value) - s.PutCString(return_value); - else - { - if (m_error.Fail()) - s.Printf("<%s>", m_error.AsCString()); - else if (val_obj_display == eDisplaySummary) - s.PutCString(""); - else if (val_obj_display == eDisplayValue) - s.PutCString(""); - else if (val_obj_display == eDisplayLanguageSpecific) - s.PutCString(""); // edit this if we have other runtimes that support a description - else - s.PutCString(""); - } - - // we should only return false here if we could not do *anything* - // even if we have an error message as output, that's a success - // from our callers' perspective, so return true - return true; - -} - // if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep // this call up to date by returning true for your new special cases. We will eventually move // to checking this call result before trying to display special cases bool -ValueObject::HasSpecialCasesForPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display, - Format custom_format) +ValueObject::HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display, + Format custom_format) { clang_type_t elem_or_pointee_type; Flags flags(ClangASTContext::GetTypeInfo(GetClangType(), GetClangAST(), &elem_or_pointee_type)); if (flags.AnySet(ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) - && val_obj_display == ValueObject::eDisplayValue) + && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { if (IsCStringContainer(true) && (custom_format == eFormatCString || @@ -1382,131 +1292,225 @@ bool ValueObject::DumpPrintableRepresentation(Stream& s, ValueObjectRepresentationStyle val_obj_display, Format custom_format, - bool only_special) + PrintableRepresentationSpecialCases special) { clang_type_t elem_or_pointee_type; Flags flags(ClangASTContext::GetTypeInfo(GetClangType(), GetClangAST(), &elem_or_pointee_type)); - if (flags.AnySet(ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) - && val_obj_display == ValueObject::eDisplayValue) + bool allow_special = ((special & ePrintableRepresentationSpecialCasesAllow) == ePrintableRepresentationSpecialCasesAllow); + bool only_special = ((special & ePrintableRepresentationSpecialCasesOnly) == ePrintableRepresentationSpecialCasesOnly); + + if (allow_special) { - // when being asked to get a printable display an array or pointer type directly, - // try to "do the right thing" - - if (IsCStringContainer(true) && - (custom_format == eFormatCString || - custom_format == eFormatCharArray || - custom_format == eFormatChar || - custom_format == eFormatVectorOfChar)) // print char[] & char* directly + if (flags.AnySet(ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) + && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { - Error error; - ReadPointedString(s, - error, - 0, - (custom_format == eFormatVectorOfChar) || - (custom_format == eFormatCharArray)); - return !error.Fail(); - } - - if (custom_format == eFormatEnum) - return false; - - // this only works for arrays, because I have no way to know when - // the pointed memory ends, and no special \0 end of data marker - if (flags.Test(ClangASTContext::eTypeIsArray)) - { - if ((custom_format == eFormatBytes) || - (custom_format == eFormatBytesWithASCII)) + // when being asked to get a printable display an array or pointer type directly, + // try to "do the right thing" + + if (IsCStringContainer(true) && + (custom_format == eFormatCString || + custom_format == eFormatCharArray || + custom_format == eFormatChar || + custom_format == eFormatVectorOfChar)) // print char[] & char* directly { - uint32_t count = GetNumChildren(); - - s << '['; - for (uint32_t low = 0; low < count; low++) - { - - if (low) - s << ','; - - ValueObjectSP child = GetChildAtIndex(low,true); - if (!child.get()) - { - s << ""; - continue; - } - child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, custom_format); - } - - s << ']'; - - return true; + Error error; + ReadPointedString(s, + error, + 0, + (custom_format == eFormatVectorOfChar) || + (custom_format == eFormatCharArray)); + return !error.Fail(); } - if ((custom_format == eFormatVectorOfChar) || - (custom_format == eFormatVectorOfFloat32) || - (custom_format == eFormatVectorOfFloat64) || - (custom_format == eFormatVectorOfSInt16) || - (custom_format == eFormatVectorOfSInt32) || - (custom_format == eFormatVectorOfSInt64) || - (custom_format == eFormatVectorOfSInt8) || - (custom_format == eFormatVectorOfUInt128) || - (custom_format == eFormatVectorOfUInt16) || - (custom_format == eFormatVectorOfUInt32) || - (custom_format == eFormatVectorOfUInt64) || - (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes with ASCII or any vector format should be printed directly + if (custom_format == eFormatEnum) + return false; + + // this only works for arrays, because I have no way to know when + // the pointed memory ends, and no special \0 end of data marker + if (flags.Test(ClangASTContext::eTypeIsArray)) { - uint32_t count = GetNumChildren(); - - Format format = FormatManager::GetSingleItemFormat(custom_format); - - s << '['; - for (uint32_t low = 0; low < count; low++) + if ((custom_format == eFormatBytes) || + (custom_format == eFormatBytesWithASCII)) { - - if (low) - s << ','; - - ValueObjectSP child = GetChildAtIndex(low,true); - if (!child.get()) + uint32_t count = GetNumChildren(); + + s << '['; + for (uint32_t low = 0; low < count; low++) { - s << ""; - continue; - } - child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, format); - } + + if (low) + s << ','; + + ValueObjectSP child = GetChildAtIndex(low,true); + if (!child.get()) + { + s << ""; + continue; + } + child->DumpPrintableRepresentation(s, ValueObject::eValueObjectRepresentationStyleValue, custom_format); + } + + s << ']'; + + return true; + } - s << ']'; - - return true; + if ((custom_format == eFormatVectorOfChar) || + (custom_format == eFormatVectorOfFloat32) || + (custom_format == eFormatVectorOfFloat64) || + (custom_format == eFormatVectorOfSInt16) || + (custom_format == eFormatVectorOfSInt32) || + (custom_format == eFormatVectorOfSInt64) || + (custom_format == eFormatVectorOfSInt8) || + (custom_format == eFormatVectorOfUInt128) || + (custom_format == eFormatVectorOfUInt16) || + (custom_format == eFormatVectorOfUInt32) || + (custom_format == eFormatVectorOfUInt64) || + (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes with ASCII or any vector format should be printed directly + { + uint32_t count = GetNumChildren(); + + Format format = FormatManager::GetSingleItemFormat(custom_format); + + s << '['; + for (uint32_t low = 0; low < count; low++) + { + + if (low) + s << ','; + + ValueObjectSP child = GetChildAtIndex(low,true); + if (!child.get()) + { + s << ""; + continue; + } + child->DumpPrintableRepresentation(s, ValueObject::eValueObjectRepresentationStyleValue, format); + } + + s << ']'; + + return true; + } } + + if ((custom_format == eFormatBoolean) || + (custom_format == eFormatBinary) || + (custom_format == eFormatChar) || + (custom_format == eFormatCharPrintable) || + (custom_format == eFormatComplexFloat) || + (custom_format == eFormatDecimal) || + (custom_format == eFormatHex) || + (custom_format == eFormatFloat) || + (custom_format == eFormatOctal) || + (custom_format == eFormatOSType) || + (custom_format == eFormatUnicode16) || + (custom_format == eFormatUnicode32) || + (custom_format == eFormatUnsigned) || + (custom_format == eFormatPointer) || + (custom_format == eFormatComplexInteger) || + (custom_format == eFormatComplex) || + (custom_format == eFormatDefault)) // use the [] operator + return false; } - - if ((custom_format == eFormatBoolean) || - (custom_format == eFormatBinary) || - (custom_format == eFormatChar) || - (custom_format == eFormatCharPrintable) || - (custom_format == eFormatComplexFloat) || - (custom_format == eFormatDecimal) || - (custom_format == eFormatHex) || - (custom_format == eFormatFloat) || - (custom_format == eFormatOctal) || - (custom_format == eFormatOSType) || - (custom_format == eFormatUnicode16) || - (custom_format == eFormatUnicode32) || - (custom_format == eFormatUnsigned) || - (custom_format == eFormatPointer) || - (custom_format == eFormatComplexInteger) || - (custom_format == eFormatComplex) || - (custom_format == eFormatDefault)) // use the [] operator - return false; } if (only_special) return false; - bool var_success = GetPrintableRepresentation(s, val_obj_display, custom_format); - if (custom_format != eFormatInvalid) - SetFormat(eFormatDefault); + bool var_success = false; + + { + const char * return_value; + std::string alloc_mem; + + if (custom_format != eFormatInvalid) + SetFormat(custom_format); + + switch(val_obj_display) + { + case eValueObjectRepresentationStyleValue: + return_value = GetValueAsCString(); + break; + + case eValueObjectRepresentationStyleSummary: + return_value = GetSummaryAsCString(); + break; + + case eValueObjectRepresentationStyleLanguageSpecific: + return_value = GetObjectDescription(); + break; + + case eValueObjectRepresentationStyleLocation: + return_value = GetLocationAsCString(); + break; + + case eValueObjectRepresentationStyleChildrenCount: + { + alloc_mem.resize(512); + return_value = &alloc_mem[0]; + int count = GetNumChildren(); + snprintf((char*)return_value, 512, "%d", count); + } + break; + + case eValueObjectRepresentationStyleType: + return_value = GetTypeName().AsCString(); + break; + + default: + break; + } + + if (!return_value) + { + if (val_obj_display == eValueObjectRepresentationStyleValue) + return_value = GetSummaryAsCString(); + else if (val_obj_display == eValueObjectRepresentationStyleSummary) + { + if (ClangASTContext::IsAggregateType (GetClangType()) == true) + { + // this thing has no value, and it seems to have no summary + // some combination of unitialized data and other factors can also + // raise this condition, so let's print a nice generic description + { + alloc_mem.resize(684); + return_value = &alloc_mem[0]; + snprintf((char*)return_value, 684, "%s @ %s", GetTypeName().AsCString(), GetLocationAsCString()); + } + } + else + return_value = GetValueAsCString(); + } + } + + if (return_value) + s.PutCString(return_value); + else + { + if (m_error.Fail()) + s.Printf("<%s>", m_error.AsCString()); + else if (val_obj_display == eValueObjectRepresentationStyleSummary) + s.PutCString(""); + else if (val_obj_display == eValueObjectRepresentationStyleValue) + s.PutCString(""); + else if (val_obj_display == eValueObjectRepresentationStyleLanguageSpecific) + s.PutCString(""); // edit this if we have other runtimes that support a description + else + s.PutCString(""); + } + + // we should only return false here if we could not do *anything* + // even if we have an error message as output, that's a success + // from our callers' perspective, so return true + var_success = true; + + if (custom_format != eFormatInvalid) + SetFormat(eFormatDefault); + } + return var_success; } @@ -1987,19 +1991,18 @@ ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_cr } void -ValueObject::CalculateSyntheticValue (SyntheticValueType use_synthetic) +ValueObject::CalculateSyntheticValue (bool use_synthetic) { - if (use_synthetic == eNoSyntheticFilter) + if (use_synthetic == false) return; - UpdateFormatsIfNeeded(m_last_format_mgr_dynamic); + if (!UpdateFormatsIfNeeded(m_last_format_mgr_dynamic) && m_synthetic_value) + return; if (m_synthetic_children_sp.get() == NULL) return; - if (m_synthetic_value == NULL) - m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp); - + m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp); } void @@ -2068,27 +2071,18 @@ ValueObject::GetStaticValue() return GetSP(); } -// GetDynamicValue() returns a NULL SharedPointer if the object is not dynamic -// or we do not really want a dynamic VO. this method instead returns this object -// itself when making it synthetic has no meaning. this makes it much simpler -// to replace the SyntheticValue for the ValueObject ValueObjectSP -ValueObject::GetSyntheticValue (SyntheticValueType use_synthetic) +ValueObject::GetSyntheticValue (bool use_synthetic) { - if (use_synthetic == eNoSyntheticFilter) - return GetSP(); - - UpdateFormatsIfNeeded(m_last_format_mgr_dynamic); - - if (m_synthetic_children_sp.get() == NULL) - return GetSP(); - + if (use_synthetic == false) + return ValueObjectSP(); + CalculateSyntheticValue(use_synthetic); if (m_synthetic_value) return m_synthetic_value->GetSP(); else - return GetSP(); + return ValueObjectSP(); } bool @@ -2099,7 +2093,7 @@ ValueObject::HasSyntheticValue() if (m_synthetic_children_sp.get() == NULL) return false; - CalculateSyntheticValue(eUseSyntheticFilter); + CalculateSyntheticValue(true); if (m_synthetic_value) return true; @@ -2146,7 +2140,7 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp { const bool is_deref_of_parent = IsDereferenceOfParent (); - if (is_deref_of_parent && epformat == eDereferencePointers) + if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers) { // this is the original format of GetExpressionPath() producing code like *(a_ptr).memberName, which is entirely // fine, until you put this into StackFrame::GetValueForVariableExpressionPath() which prefers to see a_ptr->memberName. @@ -2162,7 +2156,7 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp // if we are a deref_of_parent just because we are synthetic array // members made up to allow ptr[%d] syntax to work in variable // printing, then add our name ([%d]) to the expression path - if (m_is_array_item_for_pointer && epformat == eHonorPointers) + if (m_is_array_item_for_pointer && epformat == eGetExpressionPathFormatHonorPointers) s.PutCString(m_name.AsCString()); if (!IsBaseClass()) @@ -2177,7 +2171,7 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp { const uint32_t non_base_class_parent_type_info = ClangASTContext::GetTypeInfo (non_base_class_parent_clang_type, NULL, NULL); - if (parent && parent->IsDereferenceOfParent() && epformat == eHonorPointers) + if (parent && parent->IsDereferenceOfParent() && epformat == eGetExpressionPathFormatHonorPointers) { s.PutCString("->"); } @@ -2209,7 +2203,7 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp } } - if (is_deref_of_parent && epformat == eDereferencePointers) + if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers) { s.PutChar(')'); } @@ -2227,7 +2221,7 @@ ValueObject::GetValueForExpressionPath(const char* expression, const char* dummy_first_unparsed; ExpressionPathScanEndReason dummy_reason_to_stop; ExpressionPathEndResultType dummy_final_value_type; - ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eNothing; + ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing; ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, first_unparsed ? first_unparsed : &dummy_first_unparsed, @@ -2236,46 +2230,46 @@ ValueObject::GetValueForExpressionPath(const char* expression, options, final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); - if (!final_task_on_target || *final_task_on_target == ValueObject::eNothing) + if (!final_task_on_target || *final_task_on_target == ValueObject::eExpressionPathAftermathNothing) return ret_val; - if (ret_val.get() && ((final_value_type ? *final_value_type : dummy_final_value_type) == ePlain)) // I can only deref and takeaddress of plain objects + if (ret_val.get() && ((final_value_type ? *final_value_type : dummy_final_value_type) == eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress of plain objects { - if ( (final_task_on_target ? *final_task_on_target : dummy_final_task_on_target) == ValueObject::eDereference) + if ( (final_task_on_target ? *final_task_on_target : dummy_final_task_on_target) == ValueObject::eExpressionPathAftermathDereference) { Error error; ValueObjectSP final_value = ret_val->Dereference(error); if (error.Fail() || !final_value.get()) { if (reason_to_stop) - *reason_to_stop = ValueObject::eDereferencingFailed; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; if (final_value_type) - *final_value_type = ValueObject::eInvalid; + *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else { if (final_task_on_target) - *final_task_on_target = ValueObject::eNothing; + *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; return final_value; } } - if (*final_task_on_target == ValueObject::eTakeAddress) + if (*final_task_on_target == ValueObject::eExpressionPathAftermathTakeAddress) { Error error; ValueObjectSP final_value = ret_val->AddressOf(error); if (error.Fail() || !final_value.get()) { if (reason_to_stop) - *reason_to_stop = ValueObject::eTakingAddressFailed; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonTakingAddressFailed; if (final_value_type) - *final_value_type = ValueObject::eInvalid; + *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else { if (final_task_on_target) - *final_task_on_target = ValueObject::eNothing; + *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; return final_value; } } @@ -2295,7 +2289,7 @@ ValueObject::GetValuesForExpressionPath(const char* expression, const char* dummy_first_unparsed; ExpressionPathScanEndReason dummy_reason_to_stop; ExpressionPathEndResultType dummy_final_value_type; - ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eNothing; + ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing; ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, first_unparsed ? first_unparsed : &dummy_first_unparsed, @@ -2307,46 +2301,46 @@ ValueObject::GetValuesForExpressionPath(const char* expression, if (!ret_val.get()) // if there are errors, I add nothing to the list return 0; - if (*reason_to_stop != eArrayRangeOperatorMet) + if (*reason_to_stop != eExpressionPathScanEndReasonArrayRangeOperatorMet) { // I need not expand a range, just post-process the final value and return - if (!final_task_on_target || *final_task_on_target == ValueObject::eNothing) + if (!final_task_on_target || *final_task_on_target == ValueObject::eExpressionPathAftermathNothing) { list->Append(ret_val); return 1; } - if (ret_val.get() && *final_value_type == ePlain) // I can only deref and takeaddress of plain objects + if (ret_val.get() && *final_value_type == eExpressionPathEndResultTypePlain) // I can only deref and takeaddress of plain objects { - if (*final_task_on_target == ValueObject::eDereference) + if (*final_task_on_target == ValueObject::eExpressionPathAftermathDereference) { Error error; ValueObjectSP final_value = ret_val->Dereference(error); if (error.Fail() || !final_value.get()) { - *reason_to_stop = ValueObject::eDereferencingFailed; - *final_value_type = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else { - *final_task_on_target = ValueObject::eNothing; + *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; list->Append(final_value); return 1; } } - if (*final_task_on_target == ValueObject::eTakeAddress) + if (*final_task_on_target == ValueObject::eExpressionPathAftermathTakeAddress) { Error error; ValueObjectSP final_value = ret_val->AddressOf(error); if (error.Fail() || !final_value.get()) { - *reason_to_stop = ValueObject::eTakingAddressFailed; - *final_value_type = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonTakingAddressFailed; + *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else { - *final_task_on_target = ValueObject::eNothing; + *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; list->Append(final_value); return 1; } @@ -2399,7 +2393,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!expression_cstr || *expression_cstr == '\0') { - *reason_to_stop = ValueObject::eEndOfString; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; return root; } @@ -2411,8 +2405,8 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eArrowInsteadOfDot; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } if (root_clang_type_info.Test(ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden @@ -2420,15 +2414,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, options.m_no_fragile_ivar) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eFragileIVarNotAllowed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } if (expression_cstr[1] != '>') { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } expression_cstr++; // skip the - @@ -2439,8 +2433,8 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eDotInsteadOfArrow; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } expression_cstr++; // skip . @@ -2454,13 +2448,19 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (child_valobj_sp.get()) // we know we are done, so just return { *first_unparsed = '\0'; - *reason_to_stop = ValueObject::eEndOfString; - *final_result = ValueObject::ePlain; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; return child_valobj_sp; } else if (options.m_no_synthetic_children == false) // let's try with synthetic children { - child_valobj_sp = root->GetSyntheticValue(eNoSyntheticFilter)->GetChildMemberWithName(child_name, true); + if (root->IsSynthetic()) + child_valobj_sp = root; + else + child_valobj_sp = root->GetSyntheticValue(); + + if (child_valobj_sp.get()) + child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); } // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP, @@ -2468,15 +2468,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if(child_valobj_sp.get()) // if it worked, just return { *first_unparsed = '\0'; - *reason_to_stop = ValueObject::eEndOfString; - *final_result = ValueObject::ePlain; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; return child_valobj_sp; } else { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } } @@ -2488,12 +2488,14 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, { root = child_valobj_sp; *first_unparsed = next_separator; - *final_result = ValueObject::ePlain; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; continue; } else if (options.m_no_synthetic_children == false) // let's try with synthetic children { - child_valobj_sp = root->GetSyntheticValue(eUseSyntheticFilter)->GetChildMemberWithName(child_name, true); + child_valobj_sp = root->GetSyntheticValue(true); + if (child_valobj_sp) + child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); } // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP, @@ -2502,14 +2504,14 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, { root = child_valobj_sp; *first_unparsed = next_separator; - *final_result = ValueObject::ePlain; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; continue; } else { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } } @@ -2524,16 +2526,16 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (options.m_no_synthetic_children) // ...only chance left is synthetic { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eRangeOperatorInvalid; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } } else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eRangeOperatorNotAllowed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } } @@ -2542,15 +2544,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else // even if something follows, we cannot expand unbounded ranges, just let the caller do it { *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eArrayRangeOperatorMet; - *final_result = ValueObject::eUnboundedRange; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeUnboundedRange; return root; } } @@ -2559,8 +2561,8 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!close_bracket_position) // if there is no ], this is a syntax error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N] @@ -2570,8 +2572,8 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!end || end != close_bracket_position) // if something weird is in our way return an error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays @@ -2579,15 +2581,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eArrayRangeOperatorMet; - *final_result = ValueObject::eUnboundedRange; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeUnboundedRange; return root; } else { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } } @@ -2598,26 +2600,26 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!child_valobj_sp) child_valobj_sp = root->GetSyntheticArrayMemberFromArray(index, true); if (!child_valobj_sp) - if (root->HasSyntheticValue() && root->GetSyntheticValue(eUseSyntheticFilter)->GetNumChildren() > index) - child_valobj_sp = root->GetSyntheticValue(eUseSyntheticFilter)->GetChildAtIndex(index, true); + if (root->HasSyntheticValue() && root->GetSyntheticValue()->GetNumChildren() > index) + child_valobj_sp = root->GetSyntheticValue()->GetChildAtIndex(index, true); if (child_valobj_sp) { root = child_valobj_sp; *first_unparsed = end+1; // skip ] - *final_result = ValueObject::ePlain; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; continue; } else { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } } else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) { - if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; @@ -2625,13 +2627,13 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (error.Fail() || !root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eDereferencingFailed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else { - *what_next = eNothing; + *what_next = eExpressionPathAftermathNothing; continue; } } @@ -2646,21 +2648,21 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, && options.m_no_synthetic_children == false) { - root = root->GetSyntheticValue(eUseSyntheticFilter)->GetChildAtIndex(index, true); + root = root->GetSyntheticValue()->GetChildAtIndex(index, true); } else root = root->GetSyntheticArrayMemberFromPointer(index, true); if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else { *first_unparsed = end+1; // skip ] - *final_result = ValueObject::ePlain; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; continue; } } @@ -2671,40 +2673,58 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing { *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet; - *final_result = ValueObject::eBitfield; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonBitfieldRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; return root; } } - else if (root->HasSyntheticValue() && options.m_no_synthetic_children == false) + else if (options.m_no_synthetic_children == false) { - root = root->GetSyntheticValue(eUseSyntheticFilter)->GetChildAtIndex(index, true); + if (root->HasSyntheticValue()) + root = root->GetSyntheticValue(); + else if (!root->IsSynthetic()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } + // if we are here, then root itself is a synthetic VO.. should be good to go + if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } + root = root->GetChildAtIndex(index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else { *first_unparsed = end+1; // skip ] - *final_result = ValueObject::ePlain; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; continue; } } else { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } } @@ -2715,16 +2735,16 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!end || end != separator_position) // if something weird is in our way return an error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } unsigned long index_higher = ::strtoul (separator_position+1, &end, 0); if (!end || end != close_bracket_position) // if something weird is in our way return an error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } if (index_lower > index_higher) // swap indices if required @@ -2739,20 +2759,20 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else { *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet; - *final_result = ValueObject::eBitfield; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonBitfieldRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; return root; } } else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - *what_next == ValueObject::eDereference && + *what_next == ValueObject::eExpressionPathAftermathDereference && pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; @@ -2760,21 +2780,21 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (error.Fail() || !root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eDereferencingFailed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } else { - *what_next = ValueObject::eNothing; + *what_next = ValueObject::eExpressionPathAftermathNothing; continue; } } else { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eArrayRangeOperatorMet; - *final_result = ValueObject::eBoundedRange; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange; return root; } } @@ -2783,8 +2803,8 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, default: // some non-separator is in the way { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); break; } @@ -2822,7 +2842,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!expression_cstr || *expression_cstr == '\0') { - *reason_to_stop = ValueObject::eEndOfString; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; list->Append(root); return 1; } @@ -2836,15 +2856,15 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eRangeOperatorInvalid; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eRangeOperatorNotAllowed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } } @@ -2853,8 +2873,8 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else // expand this into list @@ -2867,8 +2887,8 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, list->Append(child); } *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eRangeOperatorExpanded; - *final_result = ValueObject::eValueObjectList; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; + *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; return max_index; // tell me number of items I added to the VOList } } @@ -2877,8 +2897,8 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!close_bracket_position) // if there is no ], this is a syntax error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N] @@ -2888,8 +2908,8 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!end || end != close_bracket_position) // if something weird is in our way return an error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays @@ -2904,15 +2924,15 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, list->Append(child); } *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eRangeOperatorExpanded; - *final_result = ValueObject::eValueObjectList; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; + *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; return max_index; // tell me number of items I added to the VOList } else { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } } @@ -2923,22 +2943,22 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else { list->Append(root); *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eRangeOperatorExpanded; - *final_result = ValueObject::eValueObjectList; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; + *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; return 1; } } else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) { - if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; @@ -2946,13 +2966,13 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (error.Fail() || !root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eDereferencingFailed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else { - *what_next = eNothing; + *what_next = eExpressionPathAftermathNothing; continue; } } @@ -2962,16 +2982,16 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else { list->Append(root); *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eRangeOperatorExpanded; - *final_result = ValueObject::eValueObjectList; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; + *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; return 1; } } @@ -2982,16 +3002,16 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing { list->Append(root); *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eRangeOperatorExpanded; - *final_result = ValueObject::eValueObjectList; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; + *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; return 1; } } @@ -3003,16 +3023,16 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!end || end != separator_position) // if something weird is in our way return an error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } unsigned long index_higher = ::strtoul (separator_position+1, &end, 0); if (!end || end != close_bracket_position) // if something weird is in our way return an error { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } if (index_lower > index_higher) // swap indices if required @@ -3027,21 +3047,21 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (!root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eNoSuchChild; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else { list->Append(root); *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eRangeOperatorExpanded; - *final_result = ValueObject::eValueObjectList; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; + *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; return 1; } } else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - *what_next == ValueObject::eDereference && + *what_next == ValueObject::eExpressionPathAftermathDereference && pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; @@ -3049,13 +3069,13 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, if (error.Fail() || !root.get()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eDereferencingFailed; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; } else { - *what_next = ValueObject::eNothing; + *what_next = ValueObject::eExpressionPathAftermathNothing; continue; } } @@ -3069,8 +3089,8 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, list->Append(child); } *first_unparsed = end+1; - *reason_to_stop = ValueObject::eRangeOperatorExpanded; - *final_result = ValueObject::eValueObjectList; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; + *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; return index_higher-index_lower+1; // tell me number of items I added to the VOList } } @@ -3079,8 +3099,8 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, default: // some non-[ separator, or something entirely wrong, is in the way { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eUnexpectedSymbol; - *final_result = ValueObject::eInvalid; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return 0; break; } @@ -3283,9 +3303,9 @@ DumpValueObject_Impl (Stream &s, if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr)) { - ValueObjectSP synth_valobj = valobj->GetSyntheticValue (options.m_use_synthetic ? - eUseSyntheticFilter : - eNoSyntheticFilter); + ValueObject* synth_valobj; + ValueObjectSP synth_valobj_sp = valobj->GetSyntheticValue (options.m_use_synthetic); + synth_valobj = (synth_valobj_sp ? synth_valobj_sp.get() : valobj); uint32_t num_children = synth_valobj->GetNumChildren(); bool print_dotdotdot = false; if (num_children) @@ -3853,14 +3873,28 @@ ValueObject::EvaluationPoint::SetUpdated () //} void -ValueObject::ClearUserVisibleData() +ValueObject::ClearUserVisibleData(uint32_t clear_mask) { - m_location_str.clear(); - m_value_str.clear(); - m_summary_str.clear(); - m_object_desc_str.clear(); - m_synthetic_value = NULL; - m_is_getting_summary = false; + if ((clear_mask & eClearUserVisibleDataItemsValue) == eClearUserVisibleDataItemsValue) + m_value_str.clear(); + + if ((clear_mask & eClearUserVisibleDataItemsLocation) == eClearUserVisibleDataItemsLocation) + m_location_str.clear(); + + if ((clear_mask & eClearUserVisibleDataItemsSummary) == eClearUserVisibleDataItemsSummary) + { + m_is_getting_summary = false; + m_summary_str.clear(); + } + + if ((clear_mask & eClearUserVisibleDataItemsDescription) == eClearUserVisibleDataItemsDescription) + m_object_desc_str.clear(); + + if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) == eClearUserVisibleDataItemsSyntheticChildren) + { + if (m_synthetic_value) + m_synthetic_value = NULL; + } } SymbolContextScope * diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp index 1e2cea34f8d0..8ef36bc9eff9 100644 --- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp +++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp @@ -15,87 +15,62 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/FormatClasses.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ValueObjectList.h" -#include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/Type.h" -#include "lldb/Symbol/Variable.h" - -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/LanguageRuntime.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" - - using namespace lldb_private; ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) : ValueObject(parent), - m_address (), - m_type_sp(), - m_use_synthetic (lldb::eUseSyntheticFilter), m_synth_sp(filter), - m_synth_filter(filter->GetFrontEnd(parent.GetSP())), + m_synth_filter_ap(filter->GetFrontEnd(parent)), m_children_byindex(), - m_name_toindex() + m_name_toindex(), + m_children_count(UINT32_MAX) { - SetName (parent.GetName()); +#ifdef LLDB_CONFIGURATION_DEBUG + std::string new_name(parent.GetName().AsCString()); + new_name += "$$__synth__"; + SetName (ConstString(new_name.c_str())); +#else + SetName(parent.GetName()); +#endif } ValueObjectSynthetic::~ValueObjectSynthetic() { - m_owning_valobj_sp.reset(); } lldb::clang_type_t ValueObjectSynthetic::GetClangTypeImpl () { - if (m_type_sp) - return m_value.GetClangType(); - else - return m_parent->GetClangType(); + return m_parent->GetClangType(); } ConstString ValueObjectSynthetic::GetTypeName() { - const bool success = UpdateValueIfNeeded(false); - if (success && m_type_sp) - return ClangASTType::GetConstTypeName (GetClangType()); - else - return m_parent->GetTypeName(); + return m_parent->GetTypeName(); } uint32_t ValueObjectSynthetic::CalculateNumChildren() { - return m_synth_filter->CalculateNumChildren(); + UpdateValueIfNeeded(); + if (m_children_count < UINT32_MAX) + return m_children_count; + return (m_children_count = m_synth_filter_ap->CalculateNumChildren()); } clang::ASTContext * ValueObjectSynthetic::GetClangASTImpl () { - const bool success = UpdateValueIfNeeded(false); - if (success && m_type_sp) - return m_type_sp->GetClangAST(); - else - return m_parent->GetClangAST (); + return m_parent->GetClangAST (); } size_t ValueObjectSynthetic::GetByteSize() { - const bool success = UpdateValueIfNeeded(false); - if (success && m_type_sp) - return m_value.GetValueByteSize(GetClangAST(), NULL); - else - return m_parent->GetByteSize(); + return m_parent->GetByteSize(); } lldb::ValueType @@ -113,17 +88,19 @@ ValueObjectSynthetic::UpdateValue () if (!m_parent->UpdateValueIfNeeded(false)) { // our parent could not update.. as we are meaningless without a parent, just stop - if (m_error.Success() && m_parent->GetError().Fail()) + if (m_parent->GetError().Fail()) m_error = m_parent->GetError(); return false; } - m_children_byindex.clear(); - m_name_toindex.clear(); - // let our backend do its update - - m_synth_filter->Update(); + if (m_synth_filter_ap->Update() == false) + { + // filter said that cached values are stale + m_children_byindex.clear(); + m_name_toindex.clear(); + m_children_count = UINT32_MAX; + } SetValueIsValid(true); return true; @@ -132,27 +109,30 @@ ValueObjectSynthetic::UpdateValue () lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex (uint32_t idx, bool can_create) { + UpdateValueIfNeeded(); + ByIndexIterator iter = m_children_byindex.find(idx); if (iter == m_children_byindex.end()) { - if (can_create && m_synth_filter != NULL) + if (can_create && m_synth_filter_ap.get() != NULL) { - lldb::ValueObjectSP synth_guy = m_synth_filter->GetChildAtIndex (idx, can_create); - m_children_byindex[idx]= synth_guy; + lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx, can_create); + m_children_byindex[idx]= synth_guy.get(); return synth_guy; } else return lldb::ValueObjectSP(); } else - return iter->second; + return iter->second->GetSP(); } lldb::ValueObjectSP ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create) { - + UpdateValueIfNeeded(); + uint32_t index = GetIndexOfChildWithName(name); if (index == UINT32_MAX) @@ -164,15 +144,17 @@ ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_ uint32_t ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name) { + UpdateValueIfNeeded(); + NameToIndexIterator iter = m_name_toindex.find(name.GetCString()); - if (iter == m_name_toindex.end() && m_synth_filter != NULL) + if (iter == m_name_toindex.end() && m_synth_filter_ap.get() != NULL) { - uint32_t index = m_synth_filter->GetIndexOfChildWithName (name); + uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name); m_name_toindex[name.GetCString()] = index; return index; } - else if (iter == m_name_toindex.end() && m_synth_filter == NULL) + else if (iter == m_name_toindex.end() && m_synth_filter_ap.get() == NULL) return UINT32_MAX; else /*if (iter != m_name_toindex.end())*/ return iter->second; diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 79b4449d3568..81bbf3f11acf 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -91,7 +91,7 @@ extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *impl extern "C" void* LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); extern "C" int LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); extern "C" void* LLDBSWIGPython_CastPyObjectToSBValue (void* data); -extern "C" void LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); +extern "C" bool LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); extern "C" bool LLDBSwigPythonCallCommand ( @@ -1654,26 +1654,28 @@ ScriptInterpreterPython::GetIndexOfChildWithName (const lldb::ScriptInterpreterO return ret_val; } -void +bool ScriptInterpreterPython::UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp) { + bool ret_val = false; + if (!implementor_sp) - return; + return ret_val; void* implementor = implementor_sp->GetObject(); if (!implementor) - return; + return ret_val; if (!g_swig_update_provider) - return; + return ret_val; { Locker py_lock(this); - g_swig_update_provider (implementor); + ret_val = g_swig_update_provider (implementor); } - return; + return ret_val; } bool diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 4b462ee4ebe7..780a26360262 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -642,7 +642,11 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, if (!child_valobj_sp) { if (no_synth_child == false) - child_valobj_sp = valobj_sp->GetSyntheticValue(eUseSyntheticFilter)->GetChildMemberWithName (child_name, true); + { + child_valobj_sp = valobj_sp->GetSyntheticValue(); + if (child_valobj_sp) + child_valobj_sp = child_valobj_sp->GetChildMemberWithName (child_name, true); + } if (no_synth_child || !child_valobj_sp) { @@ -742,7 +746,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, else if (is_objc_pointer) { // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children - ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(eUseSyntheticFilter); + ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); if (synthetic.get() == NULL /* no synthetic */ || synthetic == valobj_sp) /* synthetic is the same as the original object */ { @@ -814,7 +818,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, } else { - ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(eUseSyntheticFilter); + ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); if (no_synth_child /* synthetic is forbidden */ || synthetic.get() == NULL /* no synthetic */ || synthetic == valobj_sp) /* synthetic is the same as the original object */ diff --git a/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py b/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py index 78213c629fcc..2257a48e126a 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py @@ -127,8 +127,8 @@ class CppDataFormatterTestCase(TestBase): self.runCmd("type summary add -c Point") self.expect("frame variable iAmSomewhere", - substrs = ['x=4', - 'y=6']) + substrs = ['x = 4', + 'y = 6']) self.expect("type summary list", substrs = ['Point', diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py index 936e5bdda6f8..73a7bac40d18 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py @@ -22,14 +22,28 @@ class PythonSynthDataFormatterTestCase(TestBase): self.buildDwarf() self.data_formatter_commands() + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_rdar10960550_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.rdar10960550_formatter_commands() + + def test_rdar10960550_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.rdar10960550_formatter_commands() + + def setUp(self): # Call super's setUp(). TestBase.setUp(self) # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') + self.line2 = line_number('main.cpp', '// Set cast break point at this line.') + self.line3 = line_number('main.cpp', '// Set second cast break point at this line.') def data_formatter_commands(self): - """Test that that file and class static variables display correctly.""" + """Test using Python synthetic children provider.""" self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) self.expect("breakpoint set -f main.cpp -l %d" % self.line, @@ -184,17 +198,74 @@ class PythonSynthDataFormatterTestCase(TestBase): self.expect("frame variable f00_1", matching=False, substrs = ['fake_a = ']) - - self.runCmd("n") - - self.runCmd("script from ftsp import *") - self.runCmd("type synth add -l ftsp wrapint") - - self.expect('frame variable test_cast', - substrs = ['A', - 'B', - 'C', - 'D']) + + def rdar10960550_formatter_commands(self): + """Test that synthetic children persist stoppoints.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line2, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % + self.line2) + self.expect("breakpoint set -f main.cpp -l %d" % self.line3, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 2: file ='main.cpp', line = %d, locations = 1" % + self.line3) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("command script import ./ftsp.py --allow-reload") + self.runCmd("type synth add -l ftsp.ftsp wrapint") + + # we need to check that the VO is properly updated so that the same synthetic children are reused + # but their values change correctly across stop-points - in order to do this, self.runCmd("next") + # does not work because it forces a wipe of the stack frame - this is why we are using this more contrived + # mechanism to achieve our goal of preserving test_cast as a VO + test_cast = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().FindVariable('test_cast') + + str_cast = str(test_cast) + + if self.TraceOn(): + print str_cast + + self.assertTrue(str_cast.find('A') != -1, 'could not find A in output') + self.assertTrue(str_cast.find('B') != -1, 'could not find B in output') + self.assertTrue(str_cast.find('C') != -1, 'could not find C in output') + self.assertTrue(str_cast.find('D') != -1, 'could not find D in output') + self.assertTrue(str_cast.find("4 = '\\0'") != -1, 'could not find item 4 == 0') + + self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().StepOver() + + str_cast = str(test_cast) + + if self.TraceOn(): + print str_cast + + # we detect that all the values of the child objects have changed - but the counter-generated item + # is still fixed at 0 because it is cached - this would fail if update(self): in ftsp returned False + # or if synthetic children were not being preserved + self.assertTrue(str_cast.find('Q') != -1, 'could not find Q in output') + self.assertTrue(str_cast.find('X') != -1, 'could not find X in output') + self.assertTrue(str_cast.find('T') != -1, 'could not find T in output') + self.assertTrue(str_cast.find('F') != -1, 'could not find F in output') + self.assertTrue(str_cast.find("4 = '\\0'") != -1, 'could not find item 4 == 0') + if __name__ == '__main__': import atexit diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py index fb95ac2b54d0..0dc2c233e2a6 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py @@ -1,21 +1,23 @@ import lldb class fooSynthProvider: - def __init__(self, valobj, dict): - self.valobj = valobj; - self.int_type = valobj.GetType().GetBasicType(lldb.eBasicTypeInt) - def num_children(self): - return 3; - def get_child_at_index(self, index): - if index == 0: - child = self.valobj.GetChildMemberWithName('a'); - if index == 1: - child = self.valobj.CreateChildAtOffset ('fake_a', 1, self.int_type); - if index == 2: - child = self.valobj.GetChildMemberWithName('r'); - return child; - def get_child_index(self, name): - if name == 'a': - return 0; - if name == 'fake_a': - return 1; - return 2; + def __init__(self, valobj, dict): + self.valobj = valobj; + self.int_type = valobj.GetType().GetBasicType(lldb.eBasicTypeInt) + def num_children(self): + return 3; + def get_child_at_index(self, index): + if index == 0: + child = self.valobj.GetChildMemberWithName('a'); + if index == 1: + child = self.valobj.CreateChildAtOffset ('fake_a', 1, self.int_type); + if index == 2: + child = self.valobj.GetChildMemberWithName('r'); + return child; + def get_child_index(self, name): + if name == 'a': + return 0; + if name == 'fake_a': + return 1; + return 2; + def update(self): + return True \ No newline at end of file diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py index f618672deaad..d162b00db329 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py @@ -1,20 +1,32 @@ import lldb + +counter = 0 + class ftsp: def __init__(self, valobj, dict): self.valobj = valobj; - self.update() def num_children(self): if self.char.IsValid(): - return 4; + return 5; return 0; def get_child_index(self,name): return 0; def get_child_at_index(self,index): if index == 0: return self.x.Cast(self.char) + if index == 4: + return self.valobj.CreateValueFromExpression(str(index),'(char)('+str(self.count)+')') return self.x.CreateChildAtOffset(str(index), index, self.char); def update(self): self.x = self.valobj.GetChildMemberWithName('x'); self.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar) + global counter + self.count = counter + counter = counter + 1 + return True # important: if we return False here, or fail to return, the test will fail + +def __lldb_init_module(debugger, dict): + global counter + counter = 0 \ No newline at end of file diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp index b921915b91c5..c09630db1586 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp @@ -57,6 +57,11 @@ int main() 256*'B' + 256*256*'C'+ 256*256*256*'D'); - + // Set cast break point at this line. + test_cast.x = 'Q' + + 256*'X' + + 256*256*'T'+ + 256*256*256*'F'; + // Set second cast break point at this line. return 0; } \ No newline at end of file diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp index 07ee6cf2c443..ab27a310a4cb 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp @@ -1,4 +1,7 @@ #include +#ifdef _LIBCPP_INLINE_VISIBILITY +#undef _LIBCPP_INLINE_VISIBILITY +#endif #define _LIBCPP_INLINE_VISIBILITY #include diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp index a97db4cb21b4..a61b5ed58b29 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp @@ -1,4 +1,7 @@ #include +#ifdef _LIBCPP_INLINE_VISIBILITY +#undef _LIBCPP_INLINE_VISIBILITY +#endif #define _LIBCPP_INLINE_VISIBILITY #include typedef std::vector int_vect; diff --git a/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py b/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py index ff22e652b634..0cd2f4535100 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py @@ -149,7 +149,7 @@ class SynthDataFormatterTestCase(TestBase): # ...even if we use one-liner summaries self.runCmd("type summary add -c BagOfBags") self.expect('frame variable bag_bag', - substrs = ['(BagOfBags) bag_bag = (x.y=70, y->y[0-0]=true)']) + substrs = ['(BagOfBags) bag_bag = (x.y = 70, y->y[0-0] = true)']) self.runCmd("type summary delete BagOfBags")