[Lldb-commits] [lldb] [WIP][lldb][test] Add a layout simulator test for std::unique_ptr (PR #98330)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Jul 10 07:46:11 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Michael Buch (Michael137)
<details>
<summary>Changes</summary>
This is currently just a prototype.
This is motivated by the upcoming refactor of libc++'s `__compressed_pair` in https://github.com/llvm/llvm-project/pull/76756
As this will require changes to numerous LLDB libc++ data-formatters (see early draft https://github.com/llvm/llvm-project/pull/96538), it would be nice to have a test-suite that will actually exercise both the old and new layout. We have a matrix bot that tests old versions of Clang (but currently those only date back to Clang-15). Having them in the test-suite will give us quicker signal on what broke.
We have an existing test that exercises various layouts of `std::string` over time in `TestDataFormatterLibcxxStringSimulator.py`, but that's the only STL type we have it for.
This patch proposes a new `libcxx-simulators` directory which will take the same approach. It'll be great to have a record of how the layout of libc++ types. Eventually we'll move the `std::string` simulator into this directory too.
Some related discussion:
* https://github.com/llvm/llvm-project/pull/97568#issuecomment-2213426804
---
Full diff: https://github.com/llvm/llvm-project/pull/98330.diff
4 Files Affected:
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/compressed_pair.h (+89)
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/Makefile (+3)
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py (+32)
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp (+43)
``````````diff
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/compressed_pair.h b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/compressed_pair.h
new file mode 100644
index 0000000000000..ec978b8053646
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/compressed_pair.h
@@ -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
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/Makefile
new file mode 100644
index 0000000000000..38cfa81053488
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+override CXXFLAGS_EXTRAS += -std=c++14
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py
new file mode 100644
index 0000000000000..fe3570ff99ae5
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py
@@ -0,0 +1,32 @@
+"""
+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 range(1):
+ name = "test_r%d" % r
+ defines = ["COMPRESSED_PAIR_REV=%d" % r]
+ f = functools.partialmethod(
+ LibcxxUniquePtrDataFormatterSimulatorTestCase._run_test, defines
+ )
+ setattr(LibcxxUniquePtrDataFormatterSimulatorTestCase, name, f)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp
new file mode 100644
index 0000000000000..33066febc7623
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp
@@ -0,0 +1,43 @@
+#include "../compressed_pair.h"
+
+#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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/98330
More information about the lldb-commits
mailing list