Skip to content

Commit 12b03c9

Browse files
committed
[lldb][libc++] Adds valarray data formatters.
The code is heavily based on the vector data formatter.
1 parent 3bcb1f2 commit 12b03c9

File tree

7 files changed

+254
-0
lines changed

7 files changed

+254
-0
lines changed

lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
1717
LibCxxTuple.cpp
1818
LibCxxUnorderedMap.cpp
1919
LibCxxVariant.cpp
20+
LibCxxValarray.cpp
2021
LibCxxVector.cpp
2122
LibStdcpp.cpp
2223
LibStdcppTuple.cpp

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
750750
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
751751
"libc++ std::vector synthetic children",
752752
"^std::__[[:alnum:]]+::vector<.+>$", stl_deref_flags, true);
753+
AddCXXSynthetic(
754+
cpp_category_sp,
755+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator,
756+
"libc++ std::valarray synthetic children",
757+
"^std::__[[:alnum:]]+::valarray<.+>(( )?&)?$", stl_deref_flags, true);
753758
AddCXXSynthetic(
754759
cpp_category_sp,
755760
lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
@@ -871,6 +876,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
871876
lldb_private::formatters::LibcxxContainerSummaryProvider,
872877
"libc++ std::vector summary provider",
873878
"^std::__[[:alnum:]]+::vector<.+>$", stl_summary_flags, true);
879+
AddCXXSummary(
880+
cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
881+
"libc++ std::valarray summary provider",
882+
"^std::__[[:alnum:]]+::valarray<.+>(( )?&)?$", stl_summary_flags, true);
874883
AddCXXSummary(
875884
cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
876885
"libc++ std::list summary provider",

lldb/source/Plugins/Language/CPlusPlus/LibCxx.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ SyntheticChildrenFrontEnd *
219219
LibcxxStdVectorSyntheticFrontEndCreator(CXXSyntheticChildren *,
220220
lldb::ValueObjectSP);
221221

222+
SyntheticChildrenFrontEnd *
223+
LibcxxStdValarraySyntheticFrontEndCreator(CXXSyntheticChildren *,
224+
lldb::ValueObjectSP);
225+
222226
SyntheticChildrenFrontEnd *
223227
LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *,
224228
lldb::ValueObjectSP);
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
//===-- LibCxxValarray.cpp ------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "LibCxx.h"
10+
11+
#include "lldb/Core/ValueObject.h"
12+
#include "lldb/DataFormatters/FormattersHelpers.h"
13+
#include <optional>
14+
15+
using namespace lldb;
16+
using namespace lldb_private;
17+
using namespace lldb_private::formatters;
18+
19+
namespace lldb_private {
20+
namespace formatters {
21+
class LibcxxStdValarraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
22+
public:
23+
LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
24+
25+
~LibcxxStdValarraySyntheticFrontEnd() override;
26+
27+
size_t CalculateNumChildren() override;
28+
29+
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
30+
31+
bool Update() override;
32+
33+
bool MightHaveChildren() override;
34+
35+
size_t GetIndexOfChildWithName(ConstString name) override;
36+
37+
private:
38+
ValueObject *m_start = nullptr;
39+
ValueObject *m_finish = nullptr;
40+
CompilerType m_element_type;
41+
uint32_t m_element_size = 0;
42+
};
43+
44+
} // namespace formatters
45+
} // namespace lldb_private
46+
47+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
48+
LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
49+
: SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
50+
if (valobj_sp)
51+
Update();
52+
}
53+
54+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
55+
~LibcxxStdValarraySyntheticFrontEnd() {
56+
// these need to stay around because they are child objects who will follow
57+
// their parent's life cycle
58+
// delete m_start;
59+
// delete m_finish;
60+
}
61+
62+
size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
63+
CalculateNumChildren() {
64+
if (!m_start || !m_finish)
65+
return 0;
66+
uint64_t start_val = m_start->GetValueAsUnsigned(0);
67+
uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
68+
69+
if (start_val == 0 || finish_val == 0)
70+
return 0;
71+
72+
if (start_val >= finish_val)
73+
return 0;
74+
75+
size_t num_children = (finish_val - start_val);
76+
if (num_children % m_element_size)
77+
return 0;
78+
return num_children / m_element_size;
79+
}
80+
81+
lldb::ValueObjectSP
82+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::GetChildAtIndex(
83+
size_t idx) {
84+
if (!m_start || !m_finish)
85+
return lldb::ValueObjectSP();
86+
87+
uint64_t offset = idx * m_element_size;
88+
offset = offset + m_start->GetValueAsUnsigned(0);
89+
StreamString name;
90+
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
91+
return CreateValueObjectFromAddress(name.GetString(), offset,
92+
m_backend.GetExecutionContextRef(),
93+
m_element_type);
94+
}
95+
96+
bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::Update() {
97+
m_start = m_finish = nullptr;
98+
99+
CompilerType type = m_backend.GetCompilerType();
100+
if (type.GetNumTemplateArguments() == 0)
101+
return false;
102+
103+
m_element_type = type.GetTypeTemplateArgument(0);
104+
if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr))
105+
m_element_size = *size;
106+
107+
if (m_element_size == 0)
108+
return false;
109+
110+
ValueObjectSP start = m_backend.GetChildMemberWithName("__begin_");
111+
ValueObjectSP finish = m_backend.GetChildMemberWithName("__end_");
112+
113+
if (!start || !finish)
114+
return false;
115+
116+
m_start = start.get();
117+
m_finish = finish.get();
118+
119+
return false;
120+
}
121+
122+
bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
123+
MightHaveChildren() {
124+
return true;
125+
}
126+
127+
size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
128+
GetIndexOfChildWithName(ConstString name) {
129+
if (!m_start || !m_finish)
130+
return UINT32_MAX;
131+
return ExtractIndexFromString(name.GetCString());
132+
}
133+
134+
lldb_private::SyntheticChildrenFrontEnd *
135+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator(
136+
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
137+
if (!valobj_sp)
138+
return nullptr;
139+
return new LibcxxStdValarraySyntheticFrontEnd(valobj_sp);
140+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CXX_SOURCES := main.cpp
2+
3+
USE_LIBCPP := 1
4+
5+
include Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
Test lldb data formatter subsystem.
3+
"""
4+
5+
6+
import lldb
7+
from lldbsuite.test.decorators import *
8+
from lldbsuite.test.lldbtest import *
9+
from lldbsuite.test import lldbutil
10+
11+
12+
class LibcxxChronoDataFormatterTestCase(TestBase):
13+
@add_test_categories(["libc++"])
14+
def test_with_run_command(self):
15+
"""Test that that file and class static variables display correctly."""
16+
self.build()
17+
(self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
18+
self, "break here", lldb.SBFileSpec("main.cpp", False)
19+
)
20+
21+
self.expect(
22+
"frame variable va_int",
23+
substrs=[
24+
"va_int = size=4",
25+
"[0] = 0",
26+
"[1] = 0",
27+
"[2] = 0",
28+
"[3] = 0",
29+
"}",
30+
],
31+
)
32+
33+
lldbutil.continue_to_breakpoint(process, bkpt)
34+
self.expect(
35+
"frame variable va_int",
36+
substrs=[
37+
"va_int = size=4",
38+
"[0] = 1",
39+
"[1] = 12",
40+
"[2] = 123",
41+
"[3] = 1234",
42+
"}",
43+
],
44+
)
45+
46+
# check access-by-index
47+
self.expect("frame variable va_int[0]", substrs=["1"])
48+
self.expect("frame variable va_int[1]", substrs=["12"])
49+
self.expect("frame variable va_int[2]", substrs=["123"])
50+
self.expect("frame variable va_int[3]", substrs=["1234"])
51+
self.expect(
52+
"frame variable va_int[4]",
53+
error=True,
54+
substrs=['array index 4 is not valid for "(valarray<int>) va_int"'],
55+
)
56+
57+
self.expect(
58+
"frame variable va_double",
59+
substrs=[
60+
"va_double = size=4",
61+
"[0] = 1",
62+
"[1] = 0.5",
63+
"[2] = 0.25",
64+
"[3] = 0.125",
65+
"}",
66+
],
67+
)
68+
69+
# check access-by-index
70+
self.expect("frame variable va_double[0]", substrs=["1"])
71+
self.expect("frame variable va_double[1]", substrs=["0.5"])
72+
self.expect("frame variable va_double[2]", substrs=["0.25"])
73+
self.expect("frame variable va_double[3]", substrs=["0.125"])
74+
self.expect(
75+
"frame variable va_double[4]",
76+
error=True,
77+
substrs=['array index 4 is not valid for "(valarray<double>) va_double"'],
78+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <iostream>
2+
#include <valarray>
3+
4+
int main() {
5+
6+
std::valarray<int> va_int(4);
7+
std::cout << "break here";
8+
9+
va_int[0] = 1;
10+
va_int[1] = 12;
11+
va_int[2] = 123;
12+
va_int[3] = 1234;
13+
14+
std::valarray<double> va_double({1.0, 0.5, 0.25, 0.125});
15+
16+
std::cout << "break here\n";
17+
}

0 commit comments

Comments
 (0)