1//===-- LibCxxAtomic.cpp --------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "LibCxxAtomic.h"
10#include "lldb/DataFormatters/FormattersHelpers.h"
11
12using namespace lldb;
13using namespace lldb_private;
14using namespace lldb_private::formatters;
15
16//
17// We are supporting two versions of libc++ std::atomic
18//
19// Given std::atomic<int> i;
20//
21// The previous version of std::atomic was laid out like this
22//
23// (lldb) frame var -L -R i
24// 0x00007ffeefbff9a0: (std::__1::atomic<int>) i = {
25// 0x00007ffeefbff9a0: std::__1::__atomic_base<int, true> = {
26// 0x00007ffeefbff9a0: std::__1::__atomic_base<int, false> = {
27// 0x00007ffeefbff9a0: __a_ = 5
28// }
29// }
30// }
31//
32// In this case we need to obtain __a_ and the current version is laid out as so
33//
34// (lldb) frame var -L -R i
35// 0x00007ffeefbff9b0: (std::__1::atomic<int>) i = {
36// 0x00007ffeefbff9b0: std::__1::__atomic_base<int, true> = {
37// 0x00007ffeefbff9b0: std::__1::__atomic_base<int, false> = {
38// 0x00007ffeefbff9b0: __a_ = {
39// 0x00007ffeefbff9b0: std::__1::__cxx_atomic_base_impl<int> = {
40// 0x00007ffeefbff9b0: __a_value = 5
41// }
42// }
43// }
44// }
45//}
46//
47// In this case we need to obtain __a_value
48//
49// The below method covers both cases and returns the relevant member as a
50// ValueObjectSP
51//
52ValueObjectSP
53lldb_private::formatters::GetLibCxxAtomicValue(ValueObject &valobj) {
54 ValueObjectSP non_sythetic = valobj.GetNonSyntheticValue();
55 if (!non_sythetic)
56 return {};
57
58 ValueObjectSP member__a_ = non_sythetic->GetChildMemberWithName(name: "__a_");
59 if (!member__a_)
60 return {};
61
62 ValueObjectSP member__a_value =
63 member__a_->GetChildMemberWithName(name: "__a_value");
64 if (!member__a_value)
65 return member__a_;
66
67 return member__a_value;
68}
69
70bool lldb_private::formatters::LibCxxAtomicSummaryProvider(
71 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
72
73 if (ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj)) {
74 std::string summary;
75 if (atomic_value->GetSummaryAsCString(destination&: summary, options) &&
76 summary.size() > 0) {
77 stream.Printf(format: "%s", summary.c_str());
78 return true;
79 }
80 }
81
82 return false;
83}
84
85namespace lldb_private {
86namespace formatters {
87class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
88public:
89 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
90
91 ~LibcxxStdAtomicSyntheticFrontEnd() override = default;
92
93 llvm::Expected<uint32_t> CalculateNumChildren() override;
94
95 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
96
97 lldb::ChildCacheState Update() override;
98
99 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
100
101private:
102 ValueObject *m_real_child = nullptr;
103};
104} // namespace formatters
105} // namespace lldb_private
106
107lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
108 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
109 : SyntheticChildrenFrontEnd(*valobj_sp) {}
110
111lldb::ChildCacheState
112lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() {
113 ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj&: m_backend);
114 if (atomic_value)
115 m_real_child = GetLibCxxAtomicValue(valobj&: m_backend).get();
116
117 return lldb::ChildCacheState::eRefetch;
118}
119
120llvm::Expected<uint32_t> lldb_private::formatters::
121 LibcxxStdAtomicSyntheticFrontEnd::CalculateNumChildren() {
122 return m_real_child ? 1 : 0;
123}
124
125lldb::ValueObjectSP
126lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex(
127 uint32_t idx) {
128 if (idx == 0)
129 return m_real_child->GetSP()->Clone(new_name: ConstString("Value"));
130 return nullptr;
131}
132
133llvm::Expected<size_t>
134lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
135 GetIndexOfChildWithName(ConstString name) {
136 if (name == "Value")
137 return 0;
138 return llvm::createStringError(Fmt: "Type has no child named '%s'",
139 Vals: name.AsCString());
140}
141
142SyntheticChildrenFrontEnd *
143lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator(
144 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
145 if (valobj_sp)
146 return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp);
147 return nullptr;
148}
149

source code of lldb/source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp