tberghammer created this revision.
tberghammer added reviewers: labath, granata.enrico.
tberghammer added a subscriber: lldb-commits.
Add data formatter for libstdc++ unique_ptr
https://reviews.llvm.org/D25734
Files:
packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile
packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp
source/Plugins/Language/CPlusPlus/LibStdcpp.h
source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
Index: source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
@@ -0,0 +1,148 @@
+//===-- LibStdcpp.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibStdcpp.h"
+
+#include <memory>
+#include <vector>
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace {
+
+class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+ public:
+ explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ size_t CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+ bool Update() override;
+
+ bool MightHaveChildren() override;
+
+ size_t GetIndexOfChildWithName(const ConstString &name) override;
+
+ bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
+
+ private:
+ ValueObjectSP m_ptr_obj;
+ ValueObjectSP m_obj_obj;
+ ValueObjectSP m_del_obj;
+};
+
+} // end of anonymous namespace
+
+LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
+ lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
+ Update();
+}
+
+bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
+ ValueObjectSP valobj_backend_sp = m_backend.GetSP();
+ if (!valobj_backend_sp) return false;
+
+ ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
+ if (!valobj_sp) return false;
+
+ ValueObjectSP tuple_sp =
+ valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
+ if (!tuple_sp) return false;
+
+ std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
+ LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
+
+ m_ptr_obj = tuple_frontend->GetChildAtIndex(0);
+ if (m_ptr_obj)
+ m_ptr_obj->SetName(ConstString("pointer"));
+
+ m_del_obj = tuple_frontend->GetChildAtIndex(1);
+ if (m_del_obj)
+ m_del_obj->SetName(ConstString("deleter"));
+
+ if (m_ptr_obj) {
+ Error error;
+ m_obj_obj = m_ptr_obj->Dereference(error);
+ if (error.Success()) {
+ m_obj_obj->SetName(ConstString("object"));
+ }
+ }
+
+ return false;
+}
+
+bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
+
+lldb::ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(
+ size_t idx) {
+ if (idx == 0) return m_obj_obj;
+ if (idx == 1) return m_del_obj;
+ if (idx == 2) return m_ptr_obj;
+ return lldb::ValueObjectSP();
+}
+
+size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
+ if (m_del_obj) return 2;
+ if (m_ptr_obj && m_ptr_obj->GetValueAsUnsigned(0) != 0) return 1;
+ return 0;
+}
+
+size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
+ const ConstString &name) {
+ if (name == ConstString("obj") || name == ConstString("object")) return 0;
+ if (name == ConstString("del") || name == ConstString("deleter")) return 1;
+ if (name == ConstString("ptr") || name == ConstString("pointer")) return 2;
+ return UINT32_MAX;
+}
+
+bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
+ Stream &stream, const TypeSummaryOptions &options) {
+ if (!m_ptr_obj) return false;
+
+ if (m_ptr_obj->GetValueAsUnsigned(0) == 0) {
+ stream.Printf("nullptr");
+ } else {
+ Error error;
+ bool print_pointee = false;
+ if (m_obj_obj) {
+ if (m_obj_obj->DumpPrintableRepresentation(
+ stream, ValueObject::eValueObjectRepresentationStyleSummary,
+ lldb::eFormatInvalid,
+ ValueObject::ePrintableRepresentationSpecialCasesDisable,
+ false)) {
+ print_pointee = true;
+ }
+ }
+ if (!print_pointee)
+ stream.Printf("ptr = 0x%" PRIx64, m_ptr_obj->GetValueAsUnsigned(0));
+ }
+ return true;
+}
+
+SyntheticChildrenFrontEnd *
+lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+ return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
+ : nullptr);
+}
+
+bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
+ return formatter.GetSummary(stream, options);
+}
Index: source/Plugins/Language/CPlusPlus/LibStdcpp.h
===================================================================
--- source/Plugins/Language/CPlusPlus/LibStdcpp.h
+++ source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -31,6 +31,10 @@
const TypeSummaryOptions
&options); // libstdc++ std::shared_ptr<> and std::weak_ptr<>
+bool LibStdcppUniquePointerSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libstdc++ std::unique_ptr<>
+
SyntheticChildrenFrontEnd *
LibstdcppMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
@@ -42,6 +46,13 @@
SyntheticChildrenFrontEnd *
LibStdcppSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
+
+SyntheticChildrenFrontEnd *LibStdcppUniquePtrSyntheticFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP);
+
+SyntheticChildrenFrontEnd *LibStdcppTupleSyntheticFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP);
+
} // namespace formatters
} // namespace lldb_private
Index: packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp
@@ -0,0 +1,23 @@
+#include <memory>
+#include <string>
+
+struct Deleter {
+ void operator()(void*) {}
+
+ int a;
+ int b;
+};
+
+int
+main()
+{
+ std::unique_ptr<char> nup;
+ std::unique_ptr<int> iup(new int{123});
+ std::unique_ptr<std::string> sup(new std::string("foobar"));
+
+ std::unique_ptr<char, Deleter> ndp;
+ std::unique_ptr<int, Deleter> idp(new int{456}, Deleter{1, 2});
+ std::unique_ptr<std::string, Deleter> sdp(new std::string("baz"), Deleter{3, 4});
+
+ return 0; // Set break point at this line.
+}
Index: packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
@@ -0,0 +1,45 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+from __future__ import print_function
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class StdUniquePtrDataFormatterTestCase(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipIfFreeBSD
+ @skipIfWindows # libstdcpp not ported to Windows
+ @skipIfDarwin # doesn't compile on Darwin
+ def test_with_run_command(self):
+ self.build()
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ lldbutil.run_break_set_by_source_regexp(
+ self, "Set break point at this line.")
+ 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'])
+
+ self.expect("frame variable nup", substrs=['nup = nullptr'])
+ self.expect("frame variable iup", substrs=['iup = 123', 'object = 123'])
+ self.expect("frame variable iup.object", substrs=['object = 123'])
+ self.expect("frame variable sup", substrs=['sup = "foobar"', 'object = "foobar"'])
+ self.expect("frame variable sup.object", substrs=['object = "foobar"'])
+
+ self.expect("frame variable ndp", substrs=['ndp = nullptr'])
+ self.expect("frame variable idp", substrs=['idp = 456', 'object = 456', 'deleter = ', 'a = 1', 'b = 2'])
+ self.expect("frame variable idp.object", substrs=['object = 456'])
+ self.expect("frame variable idp.deleter", substrs=['a = 1', 'b = 2'])
+ self.expect("frame variable sdp", substrs=['sdp = "baz"', 'object = "baz"', 'deleter = ', 'a = 3', 'b = 4'])
+ self.expect("frame variable sdp.object", substrs=['object = "baz"'])
+ self.expect("frame variable sdp.deleter", substrs=['a = 3', 'b = 4'])
Index: packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile
@@ -0,0 +1,15 @@
+LEVEL = ../../../../../make
+
+CXX_SOURCES := main.cpp
+
+CXXFLAGS := -O0
+USE_LIBSTDCPP := 1
+
+# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD
+# targets. Other targets do not, which causes this test to fail.
+# This flag enables FullDebugInfo for all targets.
+ifneq (,$(findstring clang,$(CC)))
+ CFLAGS_EXTRAS += -fno-limit-debug-info
+endif
+
+include $(LEVEL)/Makefile.rules
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits