diff options
Diffstat (limited to 'source/Plugins/Language/CPlusPlus')
11 files changed, 167 insertions, 72 deletions
diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index 87b5b5947f358..5cfd978774fd0 100644 --- a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -17,6 +17,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" using namespace lldb; using namespace lldb_private; @@ -39,16 +40,17 @@ public: return; } - Status err; - TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage( - &err, lldb::eLanguageTypeC_plus_plus); - - if (!err.Success() || !type_system) { + auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage( + lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS), + std::move(err), "Failed to get scratch ClangASTContext"); return; } ClangASTContext *clang_ast_context = - llvm::dyn_cast<ClangASTContext>(type_system); + llvm::dyn_cast<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_context) { return; diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 44b9e5e24ccd9..489fa7d0ad918 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -486,8 +486,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", - ConstString("^std::__[[:alnum:]]+::list<.+>(( )?&)?$"), stl_deref_flags, - true); + // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" + // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" + ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" + "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), + stl_deref_flags, true); AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, @@ -547,8 +550,8 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_synth_flags, true); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$"))), + RegularExpression( + llvm::StringRef("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.libcxx.stddeque_SynthProvider"))); @@ -566,12 +569,6 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true); - AddCXXSummary( - cpp_category_sp, lldb_private::formatters::LibcxxFunctionSummaryProvider, - "libc++ std::function summary provider", - ConstString("^std::__[[:alnum:]]+::function<.+>$"), stl_summary_flags, - true); - stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); AddCXXSummary(cpp_category_sp, @@ -589,11 +586,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::list summary provider", ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(cpp_category_sp, - lldb_private::formatters::LibcxxContainerSummaryProvider, - "libc++ std::list summary provider", - ConstString("^std::__[[:alnum:]]+::list<.+>(( )?&)?$"), - stl_summary_flags, true); + AddCXXSummary( + cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::list summary provider", + // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" + // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" + ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" + "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), + stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", @@ -750,38 +750,32 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { false); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(true); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); @@ -860,6 +854,14 @@ static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { // FIXME because of a bug in the FormattersContainer we need to add a summary // for both X* and const X* (<rdar://problem/12717717>) AddCXXSummary( + cpp_category_sp, lldb_private::formatters::Char8StringSummaryProvider, + "char8_t * summary provider", ConstString("char8_t *"), string_flags); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::Char8StringSummaryProvider, + "char8_t [] summary provider", + ConstString("char8_t \\[[0-9]+\\]"), string_array_flags, true); + + AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags); AddCXXSummary(cpp_category_sp, @@ -896,6 +898,9 @@ static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { .SetHideItemNames(true) .SetShowMembersOneLiner(false); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider, + "char8_t summary provider", ConstString("char8_t"), + widechar_flags); AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags); diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp index 959079070accc..3ea7589d8e4a8 100644 --- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -32,6 +32,31 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +bool lldb_private::formatters::Char8StringSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + return false; + + lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); + if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) + return false; + + StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(valobj_addr); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + + if (!StringPrinter::ReadStringAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options)) { + stream.Printf("Summary Unavailable"); + return true; + } + + return true; +} + bool lldb_private::formatters::Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); @@ -128,6 +153,32 @@ bool lldb_private::formatters::WCharStringSummaryProvider( return true; } +bool lldb_private::formatters::Char8SummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + DataExtractor data; + Status error; + valobj.GetData(data, error); + + if (error.Fail()) + return false; + + std::string value; + valobj.GetValueAsCString(lldb::eFormatUnicode8, value); + if (!value.empty()) + stream.Printf("%s ", value.c_str()); + + StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(data); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + options.SetQuote('\''); + options.SetSourceSize(1); + options.SetBinaryZeroIsTerminator(false); + + return StringPrinter::ReadBufferAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options); +} + bool lldb_private::formatters::Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h index 92bef2382eac1..35498b3b568f7 100644 --- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h @@ -16,6 +16,9 @@ namespace lldb_private { namespace formatters { +bool Char8StringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t* + bool Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t* and unichar* @@ -27,6 +30,9 @@ bool Char32StringSummaryProvider( bool WCharStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // wchar_t* +bool Char8SummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t + bool Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t and unichar diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp index 815dafb6c7242..78c453cd1b3c7 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp @@ -30,8 +30,15 @@ public: ValueObjectSP GetChildAtIndex(size_t idx) override; private: + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + // Value objects created from raw data (i.e. in a different cluster) must + // be referenced via shared pointer to keep them alive, however. std::vector<ValueObjectSP> m_elements; - ValueObjectSP m_first; + ValueObject* m_first = nullptr; CompilerType m_bool_type; ByteOrder m_byte_order = eByteOrderInvalid; uint8_t m_byte_size = 0; @@ -50,7 +57,7 @@ BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) bool BitsetFrontEnd::Update() { m_elements.clear(); - m_first.reset(); + m_first = nullptr; TargetSP target_sp = m_backend.GetTargetSP(); if (!target_sp) @@ -63,7 +70,7 @@ bool BitsetFrontEnd::Update() { m_elements.assign(size, ValueObjectSP()); - m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true); + m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true).get(); return false; } @@ -86,7 +93,7 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { chunk = m_first->GetChildAtIndex(idx / *bit_size, true); } else { type = m_first->GetCompilerType(); - chunk = m_first; + chunk = m_first->GetSP(); } if (!type || !chunk) return {}; diff --git a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp index 116021588848c..b1ad171d0b0c6 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp @@ -31,7 +31,6 @@ public: private: size_t m_size = 0; - ValueObjectSP m_base_sp; }; } // namespace diff --git a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp index 4b72089c6ba2e..2f06d684f953c 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp @@ -38,16 +38,21 @@ public: } private: - ValueObjectSP m_container_sp; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + ValueObject* m_container_sp = nullptr; }; } // namespace bool QueueFrontEnd::Update() { - m_container_sp.reset(); + m_container_sp = nullptr; ValueObjectSP c_sp = m_backend.GetChildMemberWithName(ConstString("c"), true); if (!c_sp) return false; - m_container_sp = c_sp->GetSyntheticValue(); + m_container_sp = c_sp->GetSyntheticValue().get(); return false; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp index 8da7460f2275f..45294e25f0f5d 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp @@ -30,47 +30,58 @@ public: ValueObjectSP GetChildAtIndex(size_t idx) override; private: - std::vector<ValueObjectSP> m_elements; - ValueObjectSP m_base_sp; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + std::vector<ValueObject*> m_elements; + ValueObject* m_base = nullptr; }; } bool TupleFrontEnd::Update() { m_elements.clear(); - m_base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); - if (! m_base_sp) { + m_base = nullptr; + + ValueObjectSP base_sp; + base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); + if (!base_sp) { // Pre r304382 name of the base element. - m_base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); + base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); } - if (! m_base_sp) + if (!base_sp) return false; - m_elements.assign(m_base_sp->GetCompilerType().GetNumDirectBaseClasses(), - ValueObjectSP()); + m_base = base_sp.get(); + m_elements.assign(base_sp->GetCompilerType().GetNumDirectBaseClasses(), + nullptr); return false; } ValueObjectSP TupleFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= m_elements.size()) return ValueObjectSP(); - if (!m_base_sp) + if (!m_base) return ValueObjectSP(); if (m_elements[idx]) - return m_elements[idx]; + return m_elements[idx]->GetSP(); CompilerType holder_type = - m_base_sp->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); + m_base->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); if (!holder_type) return ValueObjectSP(); - ValueObjectSP holder_sp = m_base_sp->GetChildAtIndex(idx, true); + ValueObjectSP holder_sp = m_base->GetChildAtIndex(idx, true); if (!holder_sp) return ValueObjectSP(); ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0, true); if (elem_sp) m_elements[idx] = - elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())); + elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())).get(); - return m_elements[idx]; + if (m_elements[idx]) + return m_elements[idx]->GetSP(); + return ValueObjectSP(); } SyntheticChildrenFrontEnd * diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp index 491cf048e4592..62945bd3ce80b 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp @@ -184,7 +184,6 @@ public: private: size_t m_size = 0; - ValueObjectSP m_base_sp; }; } // namespace diff --git a/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp b/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp index 66624e5beb6dc..0ac7b8f8e02b0 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp @@ -37,7 +37,12 @@ public: size_t GetIndexOfChildWithName(ConstString name) override; private: - std::vector<ValueObjectSP> m_members; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + std::vector<ValueObject*> m_members; }; } // end of anonymous namespace @@ -72,7 +77,7 @@ bool LibStdcppTupleSyntheticFrontEnd::Update() { if (value_sp) { StreamString name; name.Printf("[%zd]", m_members.size()); - m_members.push_back(value_sp->Clone(ConstString(name.GetString()))); + m_members.push_back(value_sp->Clone(ConstString(name.GetString())).get()); } } } @@ -85,8 +90,8 @@ bool LibStdcppTupleSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP LibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(size_t idx) { - if (idx < m_members.size()) - return m_members[idx]; + if (idx < m_members.size() && m_members[idx]) + return m_members[idx]->GetSP(); return lldb::ValueObjectSP(); } diff --git a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp index 3860f960cb3de..cceb511cdc465 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp @@ -39,9 +39,14 @@ public: bool GetSummary(Stream &stream, const TypeSummaryOptions &options); private: - ValueObjectSP m_ptr_obj; - ValueObjectSP m_obj_obj; - ValueObjectSP m_del_obj; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + ValueObject* m_ptr_obj = nullptr; + ValueObject* m_obj_obj = nullptr; + ValueObject* m_del_obj = nullptr; ValueObjectSP GetTuple(); }; @@ -92,17 +97,17 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); if (ptr_obj) - m_ptr_obj = ptr_obj->Clone(ConstString("pointer")); + m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get(); ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); if (del_obj) - m_del_obj = del_obj->Clone(ConstString("deleter")); + m_del_obj = del_obj->Clone(ConstString("deleter")).get(); if (m_ptr_obj) { Status error; ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); if (error.Success()) { - m_obj_obj = obj_obj->Clone(ConstString("object")); + m_obj_obj = obj_obj->Clone(ConstString("object")).get(); } } @@ -113,12 +118,12 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { - if (idx == 0) - return m_ptr_obj; - if (idx == 1) - return m_del_obj; - if (idx == 2) - return m_obj_obj; + if (idx == 0 && m_ptr_obj) + return m_ptr_obj->GetSP(); + if (idx == 1 && m_del_obj) + return m_del_obj->GetSP(); + if (idx == 2 && m_obj_obj) + return m_obj_obj->GetSP(); return lldb::ValueObjectSP(); } |