Skip to content

Commit edd19f7

Browse files
Merge pull request #10498 from swiftlang/lldb/vector-summary-errors-to-6.2
[lldb][DataFormatter] Surface CalculateNumChildren errors in std::vector summary (llvm#135944)
2 parents f4418fb + 329e1ef commit edd19f7

File tree

11 files changed

+267
-43
lines changed

11 files changed

+267
-43
lines changed

lldb/packages/Python/lldbsuite/test/make/libcxx-simulators-common/compressed_pair.h

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77
namespace std {
88
namespace __lldb {
99

10-
// Post-c88580c layout
10+
#if __has_cpp_attribute(msvc::no_unique_address)
11+
#define _LLDB_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
12+
#elif __has_cpp_attribute(no_unique_address)
13+
#define _LLDB_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
14+
#endif
15+
16+
#if COMPRESSED_PAIR_REV == 0 // Post-c88580c layout
1117
struct __value_init_tag {};
1218
struct __default_init_tag {};
1319

@@ -52,6 +58,54 @@ class __compressed_pair : private __compressed_pair_elem<_T1, 0>,
5258

5359
_T1 &first() { return static_cast<_Base1 &>(*this).__get(); }
5460
};
61+
#elif COMPRESSED_PAIR_REV == 1
62+
// From libc++ datasizeof.h
63+
template <class _Tp> struct _FirstPaddingByte {
64+
_LLDB_NO_UNIQUE_ADDRESS _Tp __v_;
65+
char __first_padding_byte_;
66+
};
67+
68+
template <class _Tp>
69+
inline const size_t __datasizeof_v =
70+
__builtin_offsetof(_FirstPaddingByte<_Tp>, __first_padding_byte_);
71+
72+
template <class _Tp>
73+
struct __lldb_is_final : public integral_constant<bool, __is_final(_Tp)> {};
74+
75+
template <class _ToPad> class __compressed_pair_padding {
76+
char __padding_[((is_empty<_ToPad>::value &&
77+
!__lldb_is_final<_ToPad>::value) ||
78+
is_reference<_ToPad>::value)
79+
? 0
80+
: sizeof(_ToPad) - __datasizeof_v<_ToPad>];
81+
};
82+
83+
#define _LLDB_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
84+
[[__gnu__::__aligned__( \
85+
alignof(T2))]] _LLDB_NO_UNIQUE_ADDRESS T1 Initializer1; \
86+
_LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding<T1> __padding1_; \
87+
_LLDB_NO_UNIQUE_ADDRESS T2 Initializer2; \
88+
_LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding<T2> __padding2_;
89+
90+
#define _LLDB_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, \
91+
Initializer3) \
92+
[[using __gnu__: __aligned__(alignof(T2)), \
93+
__aligned__(alignof(T3))]] _LLDB_NO_UNIQUE_ADDRESS T1 Initializer1; \
94+
_LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding<T1> __padding1_; \
95+
_LLDB_NO_UNIQUE_ADDRESS T2 Initializer2; \
96+
_LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding<T2> __padding2_; \
97+
_LLDB_NO_UNIQUE_ADDRESS T3 Initializer3; \
98+
_LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding<T3> __padding3_;
99+
#elif COMPRESSED_PAIR_REV == 2
100+
#define _LLDB_COMPRESSED_PAIR(T1, Name1, T2, Name2) \
101+
_LLDB_NO_UNIQUE_ADDRESS T1 Name1; \
102+
_LLDB_NO_UNIQUE_ADDRESS T2 Name2
103+
104+
#define _LLDB_COMPRESSED_TRIPLE(T1, Name1, T2, Name2, T3, Name3) \
105+
_LLDB_NO_UNIQUE_ADDRESS T1 Name1; \
106+
_LLDB_NO_UNIQUE_ADDRESS T2 Name2; \
107+
_LLDB_NO_UNIQUE_ADDRESS T3 Name3
108+
#endif
55109
} // namespace __lldb
56110
} // namespace std
57111

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,30 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::
8787
llvm::Expected<uint32_t> lldb_private::formatters::
8888
LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren() {
8989
if (!m_start || !m_finish)
90-
return 0;
90+
return llvm::createStringError(
91+
"Failed to determine start/end of vector data.");
92+
9193
uint64_t start_val = m_start->GetValueAsUnsigned(0);
9294
uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
9395

94-
if (start_val == 0 || finish_val == 0)
96+
// A default-initialized empty vector.
97+
if (start_val == 0 && finish_val == 0)
9598
return 0;
9699

97-
if (start_val >= finish_val)
98-
return 0;
100+
if (start_val == 0)
101+
return llvm::createStringError("Invalid value for start of vector.");
102+
103+
if (finish_val == 0)
104+
return llvm::createStringError("Invalid value for end of vector.");
105+
106+
if (start_val > finish_val)
107+
return llvm::createStringError(
108+
"Start of vector data begins after end pointer.");
99109

100110
size_t num_children = (finish_val - start_val);
101111
if (num_children % m_element_size)
102-
return 0;
112+
return llvm::createStringError("Size not multiple of element size.");
113+
103114
return num_children / m_element_size;
104115
}
105116

lldb/source/ValueObject/ValueObject.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,10 +1589,16 @@ bool ValueObject::DumpPrintableRepresentation(
15891589
str = GetLocationAsCString();
15901590
break;
15911591

1592-
case eValueObjectRepresentationStyleChildrenCount:
1593-
strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors());
1594-
str = strm.GetString();
1592+
case eValueObjectRepresentationStyleChildrenCount: {
1593+
if (auto err = GetNumChildren()) {
1594+
strm.Printf("%" PRIu32, *err);
1595+
str = strm.GetString();
1596+
} else {
1597+
strm << "error: " << toString(err.takeError());
1598+
str = strm.GetString();
1599+
}
15951600
break;
1601+
}
15961602

15971603
case eValueObjectRepresentationStyleType:
15981604
str = GetTypeName().GetStringRef();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
override CXXFLAGS_EXTRAS += -std=c++20
3+
include Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Test we can understand various layouts of the libc++'s std::string
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+
import functools
11+
12+
13+
class LibcxxInvalidVectorDataFormatterSimulatorTestCase(TestBase):
14+
NO_DEBUG_INFO_TESTCASE = True
15+
16+
def test(self):
17+
self.build()
18+
lldbutil.run_to_source_breakpoint(self, "return 0", lldb.SBFileSpec("main.cpp"))
19+
20+
self.expect(
21+
"frame variable v1",
22+
substrs=["size=error: Invalid value for end of vector."],
23+
)
24+
self.expect(
25+
"frame variable v2",
26+
substrs=["size=error: Invalid value for start of vector."],
27+
)
28+
self.expect(
29+
"frame variable v3",
30+
substrs=["size=error: Start of vector data begins after end pointer."],
31+
)
32+
self.expect(
33+
"frame variable v4",
34+
substrs=["size=error: Failed to determine start/end of vector data."],
35+
)
36+
self.expect(
37+
"frame variable v5",
38+
substrs=["size=error: Size not multiple of element size."],
39+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#define COMPRESSED_PAIR_REV 2
2+
#include <libcxx-simulators-common/compressed_pair.h>
3+
4+
namespace std {
5+
inline namespace __1 {
6+
template <typename T> struct vector {
7+
T *__begin_;
8+
T *__end_;
9+
_LLDB_COMPRESSED_PAIR(T *, __cap_ = nullptr, void *, __alloc_);
10+
};
11+
} // namespace __1
12+
13+
inline namespace __2 {
14+
template <typename T> struct vector {};
15+
} // namespace __2
16+
17+
inline namespace __3 {
18+
template <typename T> struct vector {
19+
T *__begin_;
20+
T *__end_;
21+
_LLDB_COMPRESSED_PAIR(short *, __cap_ = nullptr, void *, __alloc_);
22+
};
23+
} // namespace __3
24+
} // namespace std
25+
26+
int main() {
27+
int arr[] = {1, 2, 3};
28+
std::__1::vector<int> v1{.__begin_ = arr, .__end_ = nullptr};
29+
std::__1::vector<int> v2{.__begin_ = nullptr, .__end_ = arr};
30+
std::__1::vector<int> v3{.__begin_ = &arr[2], .__end_ = arr};
31+
std::__2::vector<int> v4;
32+
33+
char carr[] = {'a'};
34+
std::__3::vector<char> v5{.__begin_ = carr, .__end_ = carr + 1};
35+
36+
return 0;
37+
}

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/TestDataFormatterLibcxxStringSimulator.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
class LibcxxStringDataFormatterSimulatorTestCase(TestBase):
1414
NO_DEBUG_INFO_TESTCASE = True
1515

16+
@skipIfDarwin
17+
@skipIfWindows
1618
def _run_test(self, defines):
1719
cxxflags_extras = " ".join(["-D%s" % d for d in defines])
1820
self.build(dictionary=dict(CXXFLAGS_EXTRAS=cxxflags_extras))
@@ -22,15 +24,19 @@ def _run_test(self, defines):
2224
self.expect_var_path("shortstring", summary='"short"')
2325
self.expect_var_path("longstring", summary='"I am a very long string"')
2426

27+
self.expect_expr("shortstring", result_summary='"short"')
28+
self.expect_expr("longstring", result_summary='"I am a very long string"')
29+
2530

2631
for v in [None, "ALTERNATE_LAYOUT"]:
27-
for r in range(5):
28-
name = "test_r%d" % r
29-
defines = ["REVISION=%d" % r]
30-
if v:
31-
name += "_" + v
32-
defines += [v]
33-
f = functools.partialmethod(
34-
LibcxxStringDataFormatterSimulatorTestCase._run_test, defines
35-
)
36-
setattr(LibcxxStringDataFormatterSimulatorTestCase, name, f)
32+
for r in range(6):
33+
for c in range(3):
34+
name = "test_r%d_c%d" % (r, c)
35+
defines = ["REVISION=%d" % r, "COMPRESSED_PAIR_REV=%d" % c]
36+
if v:
37+
name += "_" + v
38+
defines += [v]
39+
f = functools.partialmethod(
40+
LibcxxStringDataFormatterSimulatorTestCase._run_test, defines
41+
)
42+
setattr(LibcxxStringDataFormatterSimulatorTestCase, name, f)

0 commit comments

Comments
 (0)