[OpenACC] Treat 'delete' as a valid clause during parsing in C++ mode
[llvm-project.git] / lldb / unittests / SymbolFile / NativePDB / UdtRecordCompleterTests.cpp
blob17284b61b9a6ee1c522115c7ebc985f7859caa13
1 //===-- UdtRecordCompleterTests.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 //===----------------------------------------------------------------------===//
9 #include "Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h"
10 #include "llvm/ADT/StringExtras.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
14 using namespace lldb_private::npdb;
15 using namespace llvm;
17 namespace {
18 using Member = UdtRecordCompleter::Member;
19 using MemberUP = std::unique_ptr<Member>;
20 using Record = UdtRecordCompleter::Record;
22 class WrappedMember {
23 public:
24 WrappedMember(const Member &obj) : m_obj(obj) {}
26 private:
27 const Member &m_obj;
29 friend bool operator==(const WrappedMember &lhs, const WrappedMember &rhs) {
30 return lhs.m_obj.kind == rhs.m_obj.kind &&
31 lhs.m_obj.name == rhs.m_obj.name &&
32 lhs.m_obj.bit_offset == rhs.m_obj.bit_offset &&
33 lhs.m_obj.bit_size == rhs.m_obj.bit_size &&
34 lhs.m_obj.base_offset == rhs.m_obj.base_offset &&
35 std::equal(lhs.m_obj.fields.begin(), lhs.m_obj.fields.end(),
36 rhs.m_obj.fields.begin(), rhs.m_obj.fields.end(),
37 [](const MemberUP &lhs, const MemberUP &rhs) {
38 return WrappedMember(*lhs) == WrappedMember(*rhs);
39 });
42 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
43 const WrappedMember &w) {
44 os << llvm::formatv("Member{.kind={0}, .name=\"{1}\", .bit_offset={2}, "
45 ".bit_size={3}, .base_offset={4}, .fields=[",
46 w.m_obj.kind, w.m_obj.name, w.m_obj.bit_offset,
47 w.m_obj.bit_size, w.m_obj.base_offset);
48 llvm::ListSeparator sep;
49 for (auto &f : w.m_obj.fields)
50 os << sep << WrappedMember(*f);
51 return os << "]}";
55 class WrappedRecord {
56 public:
57 WrappedRecord(const Record &obj) : m_obj(obj) {}
59 private:
60 const Record &m_obj;
62 friend bool operator==(const WrappedRecord &lhs, const WrappedRecord &rhs) {
63 return lhs.m_obj.start_offset == rhs.m_obj.start_offset &&
64 std::equal(
65 lhs.m_obj.record.fields.begin(), lhs.m_obj.record.fields.end(),
66 rhs.m_obj.record.fields.begin(), rhs.m_obj.record.fields.end(),
67 [](const MemberUP &lhs, const MemberUP &rhs) {
68 return WrappedMember(*lhs) == WrappedMember(*rhs);
69 });
72 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
73 const WrappedRecord &w) {
74 os << llvm::formatv("Record{.start_offset={0}, .record.fields=[",
75 w.m_obj.start_offset);
76 llvm::ListSeparator sep;
77 for (const MemberUP &f : w.m_obj.record.fields)
78 os << sep << WrappedMember(*f);
79 return os << "]}";
83 class UdtRecordCompleterRecordTests : public testing::Test {
84 protected:
85 Record record;
87 public:
88 void SetKind(Member::Kind kind) { record.record.kind = kind; }
89 void CollectMember(StringRef name, uint64_t byte_offset, uint64_t byte_size) {
90 record.CollectMember(name, byte_offset * 8, byte_size * 8,
91 clang::QualType(), lldb::eAccessPublic, 0);
93 void ConstructRecord() { record.ConstructRecord(); }
95 Member *AddField(Member *member, StringRef name, uint64_t byte_offset,
96 uint64_t byte_size, Member::Kind kind,
97 uint64_t base_offset = 0) {
98 auto field =
99 std::make_unique<Member>(name, byte_offset * 8, byte_size * 8,
100 clang::QualType(), lldb::eAccessPublic, 0);
101 field->kind = kind;
102 field->base_offset = base_offset;
103 member->fields.push_back(std::move(field));
104 return member->fields.back().get();
106 } // namespace
108 TEST_F(UdtRecordCompleterRecordTests, TestAnonymousUnionInStruct) {
109 SetKind(Member::Kind::Struct);
110 CollectMember("m1", 0, 4);
111 CollectMember("m2", 0, 4);
112 CollectMember("m3", 0, 1);
113 CollectMember("m4", 0, 8);
114 ConstructRecord();
116 // struct {
117 // union {
118 // m1;
119 // m2;
120 // m3;
121 // m4;
122 // };
123 // };
124 Record record;
125 record.start_offset = 0;
126 Member *u = AddField(&record.record, "", 0, 0, Member::Union);
127 AddField(u, "m1", 0, 4, Member::Field);
128 AddField(u, "m2", 0, 4, Member::Field);
129 AddField(u, "m3", 0, 1, Member::Field);
130 AddField(u, "m4", 0, 8, Member::Field);
131 EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));
134 TEST_F(UdtRecordCompleterRecordTests, TestAnonymousUnionInUnion) {
135 SetKind(Member::Kind::Union);
136 CollectMember("m1", 0, 4);
137 CollectMember("m2", 0, 4);
138 CollectMember("m3", 0, 1);
139 CollectMember("m4", 0, 8);
140 ConstructRecord();
142 // union {
143 // m1;
144 // m2;
145 // m3;
146 // m4;
147 // };
148 Record record;
149 record.start_offset = 0;
150 AddField(&record.record, "m1", 0, 4, Member::Field);
151 AddField(&record.record, "m2", 0, 4, Member::Field);
152 AddField(&record.record, "m3", 0, 1, Member::Field);
153 AddField(&record.record, "m4", 0, 8, Member::Field);
154 EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));
157 TEST_F(UdtRecordCompleterRecordTests, TestAnonymousStructInUnion) {
158 SetKind(Member::Kind::Union);
159 CollectMember("m1", 0, 4);
160 CollectMember("m2", 4, 4);
161 CollectMember("m3", 8, 1);
162 ConstructRecord();
164 // union {
165 // struct {
166 // m1;
167 // m2;
168 // m3;
169 // };
170 // };
171 Record record;
172 record.start_offset = 0;
173 Member *s = AddField(&record.record, "", 0, 0, Member::Kind::Struct);
174 AddField(s, "m1", 0, 4, Member::Field);
175 AddField(s, "m2", 4, 4, Member::Field);
176 AddField(s, "m3", 8, 1, Member::Field);
177 EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));
180 TEST_F(UdtRecordCompleterRecordTests, TestNestedUnionStructInStruct) {
181 SetKind(Member::Kind::Struct);
182 CollectMember("m1", 0, 4);
183 CollectMember("m2", 0, 2);
184 CollectMember("m3", 0, 2);
185 CollectMember("m4", 2, 4);
186 CollectMember("m5", 3, 2);
187 ConstructRecord();
189 // struct {
190 // union {
191 // m1;
192 // struct {
193 // m2;
194 // m5;
195 // };
196 // struct {
197 // m3;
198 // m4;
199 // };
200 // };
201 // };
202 Record record;
203 record.start_offset = 0;
204 Member *u = AddField(&record.record, "", 0, 0, Member::Union);
205 AddField(u, "m1", 0, 4, Member::Field);
206 Member *s1 = AddField(u, "", 0, 0, Member::Struct);
207 Member *s2 = AddField(u, "", 0, 0, Member::Struct);
208 AddField(s1, "m2", 0, 2, Member::Field);
209 AddField(s1, "m5", 3, 2, Member::Field);
210 AddField(s2, "m3", 0, 2, Member::Field);
211 AddField(s2, "m4", 2, 4, Member::Field);
212 EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));
215 TEST_F(UdtRecordCompleterRecordTests, TestNestedUnionStructInUnion) {
216 SetKind(Member::Kind::Union);
217 CollectMember("m1", 0, 4);
218 CollectMember("m2", 0, 2);
219 CollectMember("m3", 0, 2);
220 CollectMember("m4", 2, 4);
221 CollectMember("m5", 3, 2);
222 ConstructRecord();
224 // union {
225 // m1;
226 // struct {
227 // m2;
228 // m5;
229 // };
230 // struct {
231 // m3;
232 // m4;
233 // };
234 // };
235 Record record;
236 record.start_offset = 0;
237 AddField(&record.record, "m1", 0, 4, Member::Field);
238 Member *s1 = AddField(&record.record, "", 0, 0, Member::Struct);
239 Member *s2 = AddField(&record.record, "", 0, 0, Member::Struct);
240 AddField(s1, "m2", 0, 2, Member::Field);
241 AddField(s1, "m5", 3, 2, Member::Field);
242 AddField(s2, "m3", 0, 2, Member::Field);
243 AddField(s2, "m4", 2, 4, Member::Field);
244 EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));