-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[lldb][test] Add a layout simulator test for std::unique_ptr #98330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
a25b3c8
b25d2ab
1575ca2
69c2a7c
1996194
c13766b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
#ifndef STD_LLDB_COMPRESSED_PAIR_H | ||
#define STD_LLDB_COMPRESSED_PAIR_H | ||
|
||
#include <__memory/compressed_pair.h> | ||
#include <type_traits> | ||
|
||
namespace std { | ||
namespace __lldb { | ||
|
||
#if COMPRESSED_PAIR_REV == 0 // Post-c88580c layout | ||
struct __value_init_tag {}; | ||
struct __default_init_tag {}; | ||
|
||
template <class _Tp, int _Idx, | ||
bool _CanBeEmptyBase = | ||
std::is_empty<_Tp>::value && !std::is_final<_Tp>::value> | ||
struct __compressed_pair_elem { | ||
explicit __compressed_pair_elem(__default_init_tag) {} | ||
explicit __compressed_pair_elem(__value_init_tag) : __value_() {} | ||
|
||
explicit __compressed_pair_elem(_Tp __t) : __value_(__t) {} | ||
|
||
_Tp &__get() { return __value_; } | ||
|
||
private: | ||
_Tp __value_; | ||
}; | ||
|
||
template <class _Tp, int _Idx> | ||
struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { | ||
explicit __compressed_pair_elem(_Tp __t) : _Tp(__t) {} | ||
explicit __compressed_pair_elem(__default_init_tag) {} | ||
explicit __compressed_pair_elem(__value_init_tag) : _Tp() {} | ||
|
||
_Tp &__get() { return *this; } | ||
}; | ||
|
||
template <class _T1, class _T2> | ||
class __compressed_pair : private __compressed_pair_elem<_T1, 0>, | ||
private __compressed_pair_elem<_T2, 1> { | ||
public: | ||
using _Base1 = __compressed_pair_elem<_T1, 0>; | ||
using _Base2 = __compressed_pair_elem<_T2, 1>; | ||
|
||
explicit __compressed_pair(_T1 __t1, _T2 __t2) : _Base1(__t1), _Base2(__t2) {} | ||
explicit __compressed_pair() | ||
: _Base1(__value_init_tag()), _Base2(__value_init_tag()) {} | ||
|
||
template <class _U1, class _U2> | ||
explicit __compressed_pair(_U1 &&__t1, _U2 &&__t2) | ||
: _Base1(std::forward<_U1>(__t1)), _Base2(std::forward<_U2>(__t2)) {} | ||
|
||
_T1 &first() { return static_cast<_Base1 &>(*this).__get(); } | ||
}; | ||
#elif COMPRESSED_PAIR_REV == 1 | ||
#define _LLDB_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \ | ||
[[__gnu__::__aligned__(alignof(T2))]] [[no_unique_address]] T1 Initializer1; \ | ||
[[no_unique_address]] __compressed_pair_padding<T1> _LIBCPP_CONCAT3( \ | ||
__padding1_, __LINE__, _); \ | ||
[[no_unique_address]] T2 Initializer2; \ | ||
[[no_unique_address]] __compressed_pair_padding<T2> _LIBCPP_CONCAT3( \ | ||
__padding2_, __LINE__, _) | ||
|
||
#define _LLDB_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, \ | ||
Initializer3) \ | ||
[[using __gnu__: __aligned__(alignof(T2)), \ | ||
__aligned__(alignof(T3))]] [[no_unique_address]] T1 Initializer1; \ | ||
[[no_unique_address]] __compressed_pair_padding<T1> _LIBCPP_CONCAT3( \ | ||
__padding1_, __LINE__, _); \ | ||
[[no_unique_address]] T2 Initializer2; \ | ||
[[no_unique_address]] __compressed_pair_padding<T2> _LIBCPP_CONCAT3( \ | ||
__padding2_, __LINE__, _); \ | ||
[[no_unique_address]] T3 Initializer3; \ | ||
[[no_unique_address]] __compressed_pair_padding<T3> _LIBCPP_CONCAT3( \ | ||
__padding3_, __LINE__, _) | ||
#elif COMPRESSED_PAIR_REV == 2 | ||
#define _LLDB_COMPRESSED_PAIR(T1, Name1, T2, Name2) \ | ||
[[no_unique_address]] T1 Name1; \ | ||
[[no_unique_address]] T2 Name2 | ||
|
||
#define _LLDB_COMPRESSED_TRIPLE(T1, Name1, T2, Name2, T3, Name3) \ | ||
[[no_unique_address]] T1 Name1; \ | ||
[[no_unique_address]] T2 Name2; \ | ||
[[no_unique_address]] T3 Name3 | ||
#endif | ||
} // namespace __lldb | ||
} // namespace std | ||
|
||
#endif // _H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
CXX_SOURCES := main.cpp | ||
override CXXFLAGS_EXTRAS += -std=c++14 | ||
include Makefile.rules |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
""" | ||
Test we can understand various layouts of the libc++'s std::unique_ptr | ||
""" | ||
|
||
|
||
import lldb | ||
from lldbsuite.test.decorators import * | ||
from lldbsuite.test.lldbtest import * | ||
from lldbsuite.test import lldbutil | ||
import functools | ||
|
||
|
||
class LibcxxUniquePtrDataFormatterSimulatorTestCase(TestBase): | ||
NO_DEBUG_INFO_TESTCASE = True | ||
|
||
def _run_test(self, defines): | ||
cxxflags_extras = " ".join(["-D%s" % d for d in defines]) | ||
self.build(dictionary=dict(CXXFLAGS_EXTRAS=cxxflags_extras)) | ||
lldbutil.run_to_source_breakpoint( | ||
self, "// Break here", lldb.SBFileSpec("main.cpp") | ||
) | ||
self.expect("frame variable var_up", substrs=["pointer ="]) | ||
self.expect("frame variable var_up", substrs=["deleter ="], matching=False) | ||
self.expect( | ||
"frame variable var_with_deleter_up", substrs=["pointer =", "deleter ="] | ||
) | ||
|
||
|
||
# for r in range(3): | ||
for r in [0, 2]: | ||
name = "test_r%d" % r | ||
defines = ["COMPRESSED_PAIR_REV=%d" % r] | ||
f = functools.partialmethod( | ||
LibcxxUniquePtrDataFormatterSimulatorTestCase._run_test, defines | ||
) | ||
setattr(LibcxxUniquePtrDataFormatterSimulatorTestCase, name, f) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include "../compressed_pair.h" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have some common includes in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup will do, this was the easiest for the prototype. But I'll move it to |
||
|
||
#include <__memory/allocator_traits.h> | ||
|
||
namespace std { | ||
namespace __lldb { | ||
template <class _Tp> struct default_delete { | ||
default_delete() noexcept = default; | ||
|
||
void operator()(_Tp *__ptr) const noexcept { delete __ptr; } | ||
}; | ||
|
||
template <class _Tp, class _Dp = default_delete<_Tp>> class unique_ptr { | ||
public: | ||
typedef _Tp element_type; | ||
typedef _Dp deleter_type; | ||
typedef typename __pointer<_Tp, deleter_type>::type pointer; | ||
|
||
#if COMPRESSED_PAIR_REV == 0 | ||
std::__lldb::__compressed_pair<pointer, deleter_type> __ptr_; | ||
explicit unique_ptr(pointer __p) noexcept | ||
: __ptr_(__p, std::__lldb::__value_init_tag()) {} | ||
#elif COMPRESSED_PAIR_REV == 1 || COMPRESSED_PAIR_REV == 2 | ||
_LLDB_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_); | ||
explicit unique_ptr(pointer __p) noexcept : __ptr_(__p), __deleter_() {} | ||
#endif | ||
}; | ||
} // namespace __lldb | ||
} // namespace std | ||
|
||
struct StatefulDeleter { | ||
StatefulDeleter() noexcept = default; | ||
|
||
void operator()(int *__ptr) const noexcept { delete __ptr; } | ||
|
||
int m_state = 50; | ||
}; | ||
|
||
int main() { | ||
std::__lldb::unique_ptr<int> var_up(new int(5)); | ||
std::__lldb::unique_ptr<int, StatefulDeleter> var_with_deleter_up(new int(5)); | ||
return 0; // Break here | ||
} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where are __compressed_pair_padding and _LIBCPP_CONCAT3 defined? in libc++? I don't think we want to depend on it for several reasons:
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also not sure if we really need the _LIBCPP_CONCAT3 concat thing. Since its going to produce nondeterministic (well deterministic, but it will change very easily) values, we can't really rely on it anywhere, so maybe we could just hardcode something here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea good point, relying on libc++ is what we wanted to avoid here in the first place.
__compressed_pair_padding
and_LIBCPP_CONCAT3
are currently not part of libc++ (but will be soon). I'll go with your suggestion