Skip to content

Commit d4e8921

Browse files
committed
[lldb][test] Add libcxx-simulators test for std::optional
Follow-up to the LLDB std::optional data-formatter test failure caused by llvm#110355. Two formats are supported: 1. `__val_` has type `value_type` 2. `__val_`'s type is wrapped in `std::remove_cv_t`
1 parent 19c6958 commit d4e8921

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed
Lines changed: 3 additions & 0 deletions
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,40 @@
1+
"""
2+
Test we can understand various layouts of the libc++'s std::optional
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 LibcxxOptionalDataFormatterSimulatorTestCase(TestBase):
14+
NO_DEBUG_INFO_TESTCASE = True
15+
16+
def _run_test(self, defines):
17+
cxxflags_extras = " ".join(["-D%s" % d for d in defines])
18+
self.build(dictionary=dict(CXXFLAGS_EXTRAS=cxxflags_extras))
19+
lldbutil.run_to_source_breakpoint(
20+
self, "Break here", lldb.SBFileSpec("main.cpp")
21+
)
22+
self.expect_var_path("maybe_int", summary=' Has Value=true ',
23+
children=[ValueCheck(name="Value", summary=None, value="42")])
24+
self.expect_var_path("maybe_string", summary=' Has Value=true ',
25+
children=[ValueCheck(name="Value", summary='"Hello"')])
26+
27+
self.expect_expr("maybe_int", result_summary=' Has Value=true ',
28+
result_children=[ValueCheck(name="Value", summary=None, value="42")])
29+
30+
self.expect_expr("maybe_string", result_summary=' Has Value=true ',
31+
result_children=[ValueCheck(name="Value", summary='"Hello"')])
32+
33+
34+
for r in range(2):
35+
name = f'test_r{r}'
36+
defines = [f'REVISION={r}']
37+
f = functools.partialmethod(
38+
LibcxxOptionalDataFormatterSimulatorTestCase._run_test, defines
39+
)
40+
setattr(LibcxxOptionalDataFormatterSimulatorTestCase, name, f)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#include <type_traits>
2+
3+
#if REVISION == 0
4+
// Pre-a3942b3 layout.
5+
#define HAS_REMOVE_CV
6+
#endif
7+
// REVISION == 1: current layout
8+
9+
namespace std {
10+
namespace __lldb {
11+
12+
struct in_place_t {
13+
explicit in_place_t() = default;
14+
};
15+
constexpr in_place_t in_place{};
16+
17+
template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
18+
struct __optional_destruct_base {
19+
typedef _Tp value_type;
20+
union {
21+
char __null_state_;
22+
#ifdef HAS_REMOVE_CV
23+
remove_cv_t<value_type> __val_;
24+
#else // !HAS_REMOVE_CV
25+
value_type __val_;
26+
#endif
27+
};
28+
bool __engaged_;
29+
30+
template <class... _Args>
31+
constexpr explicit __optional_destruct_base(in_place_t, _Args &&...__args)
32+
: __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
33+
};
34+
35+
template <class _Tp, bool = is_reference<_Tp>::value>
36+
struct __optional_storage_base : __optional_destruct_base<_Tp> {
37+
using __base = __optional_destruct_base<_Tp>;
38+
using value_type = _Tp;
39+
using __base::__base;
40+
};
41+
42+
template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
43+
struct __optional_copy_base : __optional_storage_base<_Tp> {
44+
using __optional_storage_base<_Tp>::__optional_storage_base;
45+
};
46+
47+
template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
48+
struct __optional_move_base : __optional_copy_base<_Tp> {
49+
using __optional_copy_base<_Tp>::__optional_copy_base;
50+
};
51+
52+
template <class _Tp, bool = is_trivially_destructible<_Tp>::value &&
53+
is_trivially_copy_constructible<_Tp>::value &&
54+
is_trivially_copy_assignable<_Tp>::value>
55+
struct __optional_copy_assign_base : __optional_move_base<_Tp> {
56+
using __optional_move_base<_Tp>::__optional_move_base;
57+
};
58+
59+
template <class _Tp, bool = is_trivially_destructible<_Tp>::value &&
60+
is_trivially_move_constructible<_Tp>::value &&
61+
is_trivially_move_assignable<_Tp>::value>
62+
struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> {
63+
using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
64+
};
65+
66+
template <bool _CanCopy, bool _CanMove> struct __sfinae_ctor_base {};
67+
68+
template <class _Tp>
69+
using __optional_sfinae_ctor_base_t =
70+
__sfinae_ctor_base<is_copy_constructible<_Tp>::value,
71+
is_move_constructible<_Tp>::value>;
72+
73+
template <bool _CanCopy, bool _CanMove> struct __sfinae_assign_base {};
74+
75+
template <class _Tp>
76+
using __optional_sfinae_assign_base_t = __sfinae_assign_base<
77+
(is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
78+
(is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)>;
79+
80+
template <class _Tp>
81+
class optional : private __optional_move_assign_base<_Tp>,
82+
private __optional_sfinae_ctor_base_t<_Tp>,
83+
private __optional_sfinae_assign_base_t<_Tp> {
84+
using __base = __optional_move_assign_base<_Tp>;
85+
86+
public:
87+
using value_type = _Tp;
88+
89+
public:
90+
template <class _Up = value_type>
91+
constexpr explicit optional(_Up &&__v)
92+
: __base(in_place, std::forward<_Up>(__v)) {}
93+
};
94+
95+
} // namespace __lldb
96+
} // namespace std
97+
98+
int main() {
99+
std::__lldb::optional<char const *> maybe_string{"Hello"};
100+
std::__lldb::optional<int> maybe_int{42};
101+
__builtin_printf("Break here\n");
102+
return 0;
103+
}

0 commit comments

Comments
 (0)