Skip to content

Commit a25b3c8

Browse files
committed
[WIP][lldb][test] Add a layout simulator test for std::unique_ptr
1 parent 918ac62 commit a25b3c8

File tree

4 files changed

+167
-0
lines changed

4 files changed

+167
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#ifndef STD_LLDB_COMPRESSED_PAIR_H
2+
#define STD_LLDB_COMPRESSED_PAIR_H
3+
4+
#include <__memory/compressed_pair.h>
5+
#include <type_traits>
6+
7+
namespace std {
8+
namespace __lldb {
9+
10+
#if COMPRESSED_PAIR_REV == 0 // Post-c88580c layout
11+
struct __value_init_tag {};
12+
struct __default_init_tag {};
13+
14+
template <class _Tp, int _Idx,
15+
bool _CanBeEmptyBase =
16+
std::is_empty<_Tp>::value && !std::is_final<_Tp>::value>
17+
struct __compressed_pair_elem {
18+
explicit __compressed_pair_elem(__default_init_tag) {}
19+
explicit __compressed_pair_elem(__value_init_tag) : __value_() {}
20+
21+
explicit __compressed_pair_elem(_Tp __t) : __value_(__t) {}
22+
23+
_Tp &__get() { return __value_; }
24+
25+
private:
26+
_Tp __value_;
27+
};
28+
29+
template <class _Tp, int _Idx>
30+
struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp {
31+
explicit __compressed_pair_elem(_Tp __t) : _Tp(__t) {}
32+
explicit __compressed_pair_elem(__default_init_tag) {}
33+
explicit __compressed_pair_elem(__value_init_tag) : _Tp() {}
34+
35+
_Tp &__get() { return *this; }
36+
};
37+
38+
template <class _T1, class _T2>
39+
class __compressed_pair : private __compressed_pair_elem<_T1, 0>,
40+
private __compressed_pair_elem<_T2, 1> {
41+
public:
42+
using _Base1 = __compressed_pair_elem<_T1, 0>;
43+
using _Base2 = __compressed_pair_elem<_T2, 1>;
44+
45+
explicit __compressed_pair(_T1 __t1, _T2 __t2) : _Base1(__t1), _Base2(__t2) {}
46+
explicit __compressed_pair()
47+
: _Base1(__value_init_tag()), _Base2(__value_init_tag()) {}
48+
49+
template <class _U1, class _U2>
50+
explicit __compressed_pair(_U1 &&__t1, _U2 &&__t2)
51+
: _Base1(std::forward<_U1>(__t1)), _Base2(std::forward<_U2>(__t2)) {}
52+
53+
_T1 &first() { return static_cast<_Base1 &>(*this).__get(); }
54+
};
55+
#elif COMPRESSED_PAIR_REV == 1
56+
#define _LLDB_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
57+
[[__gnu__::__aligned__(alignof(T2))]] [[no_unique_address]] T1 Initializer1; \
58+
[[no_unique_address]] __compressed_pair_padding<T1> _LIBCPP_CONCAT3( \
59+
__padding1_, __LINE__, _); \
60+
[[no_unique_address]] T2 Initializer2; \
61+
[[no_unique_address]] __compressed_pair_padding<T2> _LIBCPP_CONCAT3( \
62+
__padding2_, __LINE__, _)
63+
64+
#define _LLDB_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, \
65+
Initializer3) \
66+
[[using __gnu__: __aligned__(alignof(T2)), \
67+
__aligned__(alignof(T3))]] [[no_unique_address]] T1 Initializer1; \
68+
[[no_unique_address]] __compressed_pair_padding<T1> _LIBCPP_CONCAT3( \
69+
__padding1_, __LINE__, _); \
70+
[[no_unique_address]] T2 Initializer2; \
71+
[[no_unique_address]] __compressed_pair_padding<T2> _LIBCPP_CONCAT3( \
72+
__padding2_, __LINE__, _); \
73+
[[no_unique_address]] T3 Initializer3; \
74+
[[no_unique_address]] __compressed_pair_padding<T3> _LIBCPP_CONCAT3( \
75+
__padding3_, __LINE__, _)
76+
#elif COMPRESSED_PAIR_REV == 2
77+
#define _LLDB_COMPRESSED_PAIR(T1, Name1, T2, Name2) \
78+
[[no_unique_address]] T1 Name1; \
79+
[[no_unique_address]] T2 Name2
80+
81+
#define _LLDB_COMPRESSED_TRIPLE(T1, Name1, T2, Name2, T3, Name3) \
82+
[[no_unique_address]] T1 Name1; \
83+
[[no_unique_address]] T2 Name2; \
84+
[[no_unique_address]] T3 Name3
85+
#endif
86+
} // namespace __lldb
87+
} // namespace std
88+
89+
#endif // _H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
override CXXFLAGS_EXTRAS += -std=c++14
3+
include Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""
2+
Test we can understand various layouts of the libc++'s std::unique_ptr
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+
class LibcxxUniquePtrDataFormatterSimulatorTestCase(TestBase):
13+
NO_DEBUG_INFO_TESTCASE = True
14+
15+
def _run_test(self, defines):
16+
cxxflags_extras = " ".join(["-D%s" % d for d in defines])
17+
self.build(dictionary=dict(CXXFLAGS_EXTRAS=cxxflags_extras))
18+
lldbutil.run_to_source_breakpoint(
19+
self, "// Break here", lldb.SBFileSpec("main.cpp")
20+
)
21+
self.expect("frame variable var_up", substrs=["pointer ="])
22+
self.expect("frame variable var_up", substrs=["deleter ="], matching=False)
23+
self.expect("frame variable var_with_deleter_up", substrs=["pointer =", "deleter ="])
24+
25+
#for r in range(3):
26+
for r in range(1):
27+
name = "test_r%d" % r
28+
defines = ["COMPRESSED_PAIR_REV=%d" % r]
29+
f = functools.partialmethod(
30+
LibcxxUniquePtrDataFormatterSimulatorTestCase._run_test, defines
31+
)
32+
setattr(LibcxxUniquePtrDataFormatterSimulatorTestCase, name, f)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "../compressed_pair.h"
2+
3+
#include <__memory/allocator_traits.h>
4+
5+
namespace std {
6+
namespace __lldb {
7+
template <class _Tp> struct default_delete {
8+
default_delete() noexcept = default;
9+
10+
void operator()(_Tp *__ptr) const noexcept { delete __ptr; }
11+
};
12+
13+
template <class _Tp, class _Dp = default_delete<_Tp>> class unique_ptr {
14+
public:
15+
typedef _Tp element_type;
16+
typedef _Dp deleter_type;
17+
typedef typename __pointer<_Tp, deleter_type>::type pointer;
18+
19+
#if COMPRESSED_PAIR_REV == 0
20+
std::__lldb::__compressed_pair<pointer, deleter_type> __ptr_;
21+
explicit unique_ptr(pointer __p) noexcept
22+
: __ptr_(__p, std::__lldb::__value_init_tag()) {}
23+
#elif COMPRESSED_PAIR_REV == 1 || COMPRESSED_PAIR_REV == 2
24+
_LLDB_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
25+
explicit unique_ptr(pointer __p) noexcept : __ptr_(__p), __deleter_() {}
26+
#endif
27+
};
28+
} // namespace __lldb
29+
} // namespace std
30+
31+
struct StatefulDeleter {
32+
StatefulDeleter() noexcept = default;
33+
34+
void operator()(int *__ptr) const noexcept { delete __ptr; }
35+
36+
int m_state = 50;
37+
};
38+
39+
int main() {
40+
std::__lldb::unique_ptr<int> var_up(new int(5));
41+
std::__lldb::unique_ptr<int, StatefulDeleter> var_with_deleter_up(new int(5));
42+
return 0; // Break here
43+
}

0 commit comments

Comments
 (0)