Skip to content

Commit 661f43e

Browse files
committed
[lldb][libc++] Adds valarray data formatters.
The code is heavily based on the vector data formatter.
1 parent d2e4a72 commit 661f43e

File tree

7 files changed

+259
-0
lines changed

7 files changed

+259
-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(cpp_category_sp,
880+
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: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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+
lldb::ChildCacheState Update() override;
32+
33+
bool MightHaveChildren() override;
34+
35+
size_t GetIndexOfChildWithName(ConstString name) override;
36+
37+
private:
38+
/// A non-owning pointer to valarray's __begin_ member.
39+
ValueObject *m_start = nullptr;
40+
/// A non-owning pointer to valarray's __end_ member.
41+
ValueObject *m_finish = nullptr;
42+
/// The type of valarray's template argument T.
43+
CompilerType m_element_type;
44+
/// The sizeof valarray's template argument T.
45+
uint32_t m_element_size = 0;
46+
};
47+
48+
} // namespace formatters
49+
} // namespace lldb_private
50+
51+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
52+
LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
53+
: SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
54+
if (valobj_sp)
55+
Update();
56+
}
57+
58+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
59+
~LibcxxStdValarraySyntheticFrontEnd() {
60+
// these need to stay around because they are child objects who will follow
61+
// their parent's life cycle
62+
// delete m_start;
63+
// delete m_finish;
64+
}
65+
66+
size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
67+
CalculateNumChildren() {
68+
if (!m_start || !m_finish)
69+
return 0;
70+
uint64_t start_val = m_start->GetValueAsUnsigned(0);
71+
uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
72+
73+
if (start_val == 0 || finish_val == 0)
74+
return 0;
75+
76+
if (start_val >= finish_val)
77+
return 0;
78+
79+
size_t num_children = (finish_val - start_val);
80+
if (num_children % m_element_size)
81+
return 0;
82+
return num_children / m_element_size;
83+
}
84+
85+
lldb::ValueObjectSP
86+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::GetChildAtIndex(
87+
size_t idx) {
88+
if (!m_start || !m_finish)
89+
return lldb::ValueObjectSP();
90+
91+
uint64_t offset = idx * m_element_size;
92+
offset = offset + m_start->GetValueAsUnsigned(0);
93+
StreamString name;
94+
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
95+
return CreateValueObjectFromAddress(name.GetString(), offset,
96+
m_backend.GetExecutionContextRef(),
97+
m_element_type);
98+
}
99+
100+
lldb::ChildCacheState
101+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::Update() {
102+
m_start = m_finish = nullptr;
103+
104+
CompilerType type = m_backend.GetCompilerType();
105+
if (type.GetNumTemplateArguments() == 0)
106+
return ChildCacheState::eRefetch;
107+
108+
m_element_type = type.GetTypeTemplateArgument(0);
109+
if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr))
110+
m_element_size = *size;
111+
112+
if (m_element_size == 0)
113+
return ChildCacheState::eRefetch;
114+
115+
ValueObjectSP start = m_backend.GetChildMemberWithName("__begin_");
116+
ValueObjectSP finish = m_backend.GetChildMemberWithName("__end_");
117+
118+
if (!start || !finish)
119+
return ChildCacheState::eRefetch;
120+
121+
m_start = start.get();
122+
m_finish = finish.get();
123+
124+
return ChildCacheState::eRefetch;
125+
}
126+
127+
bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
128+
MightHaveChildren() {
129+
return true;
130+
}
131+
132+
size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
133+
GetIndexOfChildWithName(ConstString name) {
134+
if (!m_start || !m_finish)
135+
return std::numeric_limits<size_t>::max();
136+
return ExtractIndexFromString(name.GetCString());
137+
}
138+
139+
lldb_private::SyntheticChildrenFrontEnd *
140+
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator(
141+
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
142+
if (!valobj_sp)
143+
return nullptr;
144+
return new LibcxxStdValarraySyntheticFrontEnd(valobj_sp);
145+
}
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)