LLDB mainline
UdtRecordCompleter.cpp
Go to the documentation of this file.
2
4#include "PdbIndex.h"
5#include "PdbSymUid.h"
6#include "PdbUtil.h"
7
12#include "SymbolFileNativePDB.h"
13#include "lldb/Core/Address.h"
14#include "lldb/Symbol/Type.h"
17#include "lldb/lldb-forward.h"
18
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/DebugInfo/CodeView/Formatters.h"
21#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
22#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
23#include "llvm/DebugInfo/CodeView/TypeIndex.h"
24#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
25#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
26#include "llvm/DebugInfo/PDB/PDBTypes.h"
27#include <optional>
28
29using namespace llvm::codeview;
30using namespace llvm::pdb;
31using namespace lldb;
32using namespace lldb_private;
33using namespace lldb_private::npdb;
34
35using Error = llvm::Error;
36
38 PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl,
39 PdbAstBuilderClang &ast_builder, PdbIndex &index,
40 llvm::DenseMap<clang::Decl *, DeclStatus> &decl_to_status,
41 llvm::DenseMap<lldb::opaque_compiler_type_t,
42 llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>>
43 &cxx_record_map)
44 : m_cv_tag_record(CVTagRecord::create(index.tpi().getType(id.index))),
45 m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
46 m_ast_builder(ast_builder), m_index(index),
47 m_decl_to_status(decl_to_status), m_cxx_record_map(cxx_record_map) {
48 switch (m_cv_tag_record.kind()) {
49 case CVTagRecord::Enum:
50 break;
51 case CVTagRecord::Union:
52 m_layout.bit_size = m_cv_tag_record.asUnion().getSize() * 8;
53 m_record.record.kind = Member::Union;
54 break;
55 case CVTagRecord::Class:
56 case CVTagRecord::Struct:
57 m_layout.bit_size = m_cv_tag_record.asClass().getSize() * 8;
58 m_record.record.kind = Member::Struct;
59 break;
60 }
61}
62
63llvm::Error
64UdtRecordCompleter::visitMemberEnd(llvm::codeview::CVMemberRecord &Record) {
66 return Error::success();
67}
68
70 llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access,
71 std::optional<uint64_t> vtable_idx) {
72 PdbTypeSymId type_id(ti);
73 clang::QualType qt = m_ast_builder.GetOrCreateClangType(type_id);
74
75 CVType udt_cvt = m_index.tpi().getType(ti);
76
77 std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
78 m_ast_builder.clang().CreateBaseClassSpecifier(
79 qt.getAsOpaquePtr(), TranslateMemberAccess(access),
80 vtable_idx.has_value(), udt_cvt.kind() == LF_CLASS);
81 if (!base_spec)
82 return {};
83
84 m_bases.push_back(
85 std::make_pair(vtable_idx.value_or(0), std::move(base_spec)));
86
87 return qt;
88}
89
90void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
91 MethodOptions options,
92 MemberAttributes attrs) {
93 clang::QualType method_qt =
94 m_ast_builder.GetOrCreateClangType(PdbTypeSymId(type_idx));
95 if (method_qt.isNull())
96 return;
97 CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
99 lldb::opaque_compiler_type_t derived_opaque_ty =
100 m_derived_ct.GetOpaqueQualType();
101 auto iter = m_cxx_record_map.find(derived_opaque_ty);
102 if (iter != m_cxx_record_map.end()) {
103 if (iter->getSecond().contains({name, method_ct})) {
104 return;
105 }
106 }
107
108 bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
109 MethodOptions::CompilerGenerated;
110 m_ast_builder.clang().AddMethodToCXXRecordType(
111 derived_opaque_ty, name.data(), /*asm_label=*/{}, method_ct,
112 attrs.isVirtual(), attrs.isStatic(), false, false, false, is_artificial);
113
114 m_cxx_record_map[derived_opaque_ty].insert({name, method_ct});
115}
116
117Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
118 BaseClassRecord &base) {
119 clang::QualType base_qt =
120 AddBaseClassForTypeIndex(base.Type, base.getAccess());
121
122 if (base_qt.isNull())
123 return llvm::Error::success();
124 auto *decl =
125 m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
126 if (!decl) {
127 LLDB_LOG(GetLog(LLDBLog::Symbols), "base ({0}) of {1} is not a record",
128 base.Type, m_id.index);
129 return Error::success();
130 }
131
132 auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
133 m_layout.base_offsets.insert(std::make_pair(decl, offset));
134
135 return llvm::Error::success();
136}
137
138Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
139 VirtualBaseClassRecord &base) {
140 // Don't create indirect virtual bases. These records indicate that at least
141 // one base class C of this class virtually inherits the specified class.
142 // We already added that virtual base when creating C. There, it's present as
143 // LF_VBCLASS.
144 if (cvr.Kind == LF_VBCLASS)
145 AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex);
146
147 return Error::success();
148}
149
150Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
151 ListContinuationRecord &cont) {
152 return Error::success();
153}
154
155Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
156 VFPtrRecord &vfptr) {
157 return Error::success();
158}
159
160Error UdtRecordCompleter::visitKnownMember(
161 CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
162 clang::QualType member_type =
163 m_ast_builder.GetOrCreateClangType(PdbTypeSymId(static_data_member.Type));
164 if (member_type.isNull())
165 return llvm::Error::success();
166
167 CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
168
170 m_derived_ct, static_data_member.Name, member_ct);
171
172 // Static constant members may be a const[expr] declaration.
173 // Query the symbol's value as the variable initializer if valid.
174 if (member_ct.IsConst() && member_ct.IsCompleteType()) {
175 // Reconstruct the full name for the static member. Use the names as given
176 // in the PDB. This ensures we match the compiler's style of names (e.g.
177 // "A<B<int> >::Foo" vs "A<B<int>>::Foo").
178 std::string qual_name =
179 (m_cv_tag_record.name() + "::" + static_data_member.Name).str();
180
181 auto results =
182 m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
183
184 for (const auto &result : results) {
185 if (result.second.kind() == SymbolKind::S_CONSTANT) {
186 ConstantSym constant(SymbolRecordKind::ConstantSym);
187 cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(result.second,
188 constant));
189
190 clang::QualType qual_type = decl->getType();
191 unsigned type_width = decl->getASTContext().getIntWidth(qual_type);
192
193 // Get the minimum bit width to encode this constant value.
194 // The bit width of the APSInt might be larger than the bits required to
195 // encode the value.
196 unsigned min_constant_width = 0;
197 if (qual_type->isUnsignedIntegerOrEnumerationType())
198 min_constant_width = constant.Value.getActiveBits();
199 else
200 min_constant_width = constant.Value.getSignificantBits();
201
202 if (qual_type->isIntegralOrEnumerationType()) {
203 if (type_width >= min_constant_width) {
205 decl, constant.Value.extOrTrunc(type_width));
206 } else {
208 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
209 "which resolves to a wider constant value ({4} bits). "
210 "Ignoring constant.",
211 m_derived_ct.GetTypeName(), static_data_member.Name,
212 member_ct.GetTypeName(), type_width, min_constant_width);
213 }
214 } else {
215 lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration();
216 switch (basic_type_enum) {
220 if (type_width == min_constant_width) {
222 decl, basic_type_enum == lldb::eBasicTypeFloat
223 ? llvm::APFloat(constant.Value.bitsToFloat())
224 : llvm::APFloat(constant.Value.bitsToDouble()));
225 decl->setConstexpr(true);
226 } else {
227 LLDB_LOG(
229 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
230 "which resolves to a constant value of mismatched width "
231 "({4} bits). Ignoring constant.",
232 m_derived_ct.GetTypeName(), static_data_member.Name,
233 member_ct.GetTypeName(), type_width, min_constant_width);
234 }
235 break;
236 default:
237 break;
238 }
239 }
240 break;
241 }
242 }
243 }
244
245 // FIXME: Add a PdbSymUid namespace for field list members and update
246 // the m_uid_to_decl map with this decl.
247 return Error::success();
248}
249
250Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
251 NestedTypeRecord &nested) {
252 // Typedefs can only be added on structs.
253 if (m_record.record.kind != Member::Struct)
254 return Error::success();
255
256 clang::QualType qt =
257 m_ast_builder.GetOrCreateClangType(PdbTypeSymId(nested.Type, false));
258 if (qt.isNull())
259 return Error::success();
260 CompilerType ct = m_ast_builder.ToCompilerType(qt);
261
262 // There's no distinction between nested types and typedefs, so check if we
263 // encountered a nested type.
264 auto *pdb = static_cast<SymbolFileNativePDB *>(
265 m_ast_builder.clang().GetSymbolFile()->GetBackingSymbolFile());
266 std::optional<TypeIndex> parent = pdb->GetParentType(nested.Type);
267 if (parent && *parent == m_id.index && ct.GetTypeName(true) == nested.Name)
268 return Error::success();
269
270 clang::DeclContext *decl_ctx =
271 m_ast_builder.GetOrCreateClangDeclContextForUid(m_id);
272 if (!decl_ctx)
273 return Error::success();
274
275 std::string name = nested.Name.str();
276 ct.CreateTypedef(name.c_str(), m_ast_builder.ToCompilerDeclContext(decl_ctx),
277 0);
278 return Error::success();
279}
280
281Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
282 DataMemberRecord &data_member) {
283
284 uint64_t offset = data_member.FieldOffset * 8;
285 uint32_t bitfield_width = 0;
286
287 TypeIndex ti(data_member.Type);
288 if (!ti.isSimple()) {
289 CVType cvt = m_index.tpi().getType(ti);
290 if (cvt.kind() == LF_BITFIELD) {
291 BitFieldRecord bfr;
292 llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
293 offset += bfr.BitOffset;
294 bitfield_width = bfr.BitSize;
295 ti = bfr.Type;
296 }
297 }
298
299 clang::QualType member_qt =
300 m_ast_builder.GetOrCreateClangType(PdbTypeSymId(ti));
301 if (member_qt.isNull())
302 return Error::success();
303 TypeSystemClang::RequireCompleteType(m_ast_builder.ToCompilerType(member_qt));
304 lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
305 size_t field_size =
306 bitfield_width ? bitfield_width : GetSizeOfType(ti, m_index.tpi()) * 8;
307 if (field_size == 0)
308 return Error::success();
309 m_record.CollectMember(data_member.Name, offset, field_size, member_qt,
310 access, bitfield_width, m_member_index);
311 return Error::success();
312}
313
314Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
315 OneMethodRecord &one_method) {
316 AddMethod(one_method.Name, one_method.Type, one_method.getOptions(),
317 one_method.Attrs);
318
319 return Error::success();
320}
321
322Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
323 OverloadedMethodRecord &overloaded) {
324 TypeIndex method_list_idx = overloaded.MethodList;
325
326 CVType method_list_type = m_index.tpi().getType(method_list_idx);
327 assert(method_list_type.kind() == LF_METHODLIST);
328
329 MethodOverloadListRecord method_list;
330 llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
331 method_list_type, method_list));
332
333 for (const OneMethodRecord &method : method_list.Methods)
334 AddMethod(overloaded.Name, method.Type, method.getOptions(), method.Attrs);
335
336 return Error::success();
337}
338
339Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
340 EnumeratorRecord &enumerator) {
341 Declaration decl;
342 llvm::StringRef name = DropNameScope(enumerator.getName());
343
344 clang::EnumDecl *enum_decl = TypeSystemClang::GetAsEnumDecl(m_derived_ct);
345 if (!enum_decl)
346 return Error::success();
347
348 llvm::APSInt val = enumerator.Value;
349 clang::QualType int_ty = enum_decl->getIntegerType();
350 uint64_t n_bits = m_ast_builder.clang().getASTContext().getTypeSize(int_ty);
351 if (n_bits == 0)
352 return Error::success();
353
354 // MSVC encodes 64 Bit unsigned enum values as signed integers. For example,
355 // ULONGLONG_MAX will be encoded as -1. LLVM encodes all values as unsigned.
356 // Fix this by explicitly setting the bit width and signedness.
357 val = val.extOrTrunc(n_bits);
358 val.setIsSigned(int_ty->isSignedIntegerType());
359
360 m_ast_builder.clang().AddEnumerationValueToEnumerationType(
361 m_derived_ct, decl, name.str().c_str(), val);
362 return Error::success();
363}
364
366 // Ensure the correct order for virtual bases.
367 llvm::stable_sort(m_bases, llvm::less_first());
368
369 std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
370 bases.reserve(m_bases.size());
371 for (auto &ib : m_bases)
372 bases.push_back(std::move(ib.second));
373
375 // Make sure all base classes refer to complete types and not forward
376 // declarations. If we don't do this, clang will crash with an
377 // assertion in the call to clang_type.TransferBaseClasses()
378 for (const auto &base_class : bases) {
379 clang::TypeSourceInfo *type_source_info =
380 base_class->getTypeSourceInfo();
381 if (type_source_info) {
383 clang.GetType(type_source_info->getType()));
384 }
385 }
386
387 clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
388
389 clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
390 FinishRecord();
393
394 if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
395 m_ast_builder.GetClangASTImporter().SetRecordLayout(record_decl, m_layout);
396 }
397}
398
399uint64_t
401 uint64_t bit_offset, CompilerType parent_ct,
402 ClangASTImporter::LayoutInfo &parent_layout,
403 clang::DeclContext *parent_decl_ctx) {
405 clang.GetSymbolFile()->GetBackingSymbolFile());
406 clang::FieldDecl *field_decl = nullptr;
407 uint64_t bit_size = 0;
408 switch (field->kind) {
409 case Member::Field: {
411 parent_ct, field->name, m_ast_builder.ToCompilerType(field->qt),
412 field->bitfield_width);
413 bit_size = field->bit_size;
414 break;
415 };
416 case Member::Struct:
417 case Member::Union: {
418 clang::TagTypeKind kind = field->kind == Member::Struct
419 ? clang::TagTypeKind::Struct
420 : clang::TagTypeKind::Union;
421 ClangASTMetadata metadata;
422 metadata.SetUserID(pdb->anonymous_id);
423 metadata.SetIsDynamicCXXType(false);
424 CompilerType record_ct = clang.CreateRecordType(
425 parent_decl_ctx, OptionalClangModuleID(), "", llvm::to_underlying(kind),
429 clang::DeclContext *decl_ctx = clang.GetDeclContextForType(record_ct);
430 for (const auto &member : field->fields) {
431 uint64_t member_offset = field->kind == Member::Struct
432 ? member->bit_offset - field->base_offset
433 : 0;
434 uint64_t member_bit_size = AddMember(clang, member.get(), member_offset,
435 record_ct, layout, decl_ctx);
436 if (field->kind == Member::Struct)
437 bit_size = std::max(bit_size, member_offset + member_bit_size);
438 else
439 bit_size = std::max(bit_size, member_bit_size);
440 }
441 layout.bit_size = bit_size;
443 clang::RecordDecl *record_decl = clang.GetAsRecordDecl(record_ct);
444 m_ast_builder.GetClangASTImporter().SetRecordLayout(record_decl, layout);
445 field_decl =
446 TypeSystemClang::AddFieldToRecordType(parent_ct, "", record_ct, 0);
447 // Mark this record decl as completed.
448 DeclStatus status;
449 status.resolved = true;
450 status.uid = pdb->anonymous_id--;
451 m_decl_to_status.insert({record_decl, status});
452 break;
453 };
454 }
455 // FIXME: Add a PdbSymUid namespace for field list members and update
456 // the m_uid_to_decl map with this decl.
457 parent_layout.field_offsets.insert({field_decl, bit_offset});
458 return bit_size;
459}
460
463 clang::DeclContext *decl_ctx =
464 m_ast_builder.GetOrCreateClangDeclContextForUid(m_id);
465 m_record.ConstructRecord();
466 // Maybe we should check the construsted record size with the size in pdb. If
467 // they mismatch, it might be pdb has fields info missing.
468 for (const auto &field : m_record.record.fields) {
469 AddMember(clang, field.get(), field->bit_offset, m_derived_ct, m_layout,
470 decl_ctx);
471 }
472}
473
475 llvm::stable_sort(fields, [](const MemberUP &lhs, const MemberUP &rhs) {
476 return std::tie(lhs->original_index, lhs->bit_offset) <
477 std::tie(rhs->original_index, rhs->bit_offset);
478 });
479
480 for (MemberUP &field : fields)
481 field->RestoreOriginalOrder();
482}
483
485 llvm::StringRef name, uint64_t offset, uint64_t field_size,
486 clang::QualType qt, lldb::AccessType access, uint64_t bitfield_width,
487 uint32_t member_index) {
488 fields_map[offset].push_back(std::make_unique<Member>(
489 name, offset, field_size, qt, access, bitfield_width, member_index));
490 if (start_offset > offset)
491 start_offset = offset;
492}
493
495 // For anonymous unions in a struct, msvc generated pdb doesn't have the
496 // entity for that union. So, we need to construct anonymous union and struct
497 // based on field offsets. The final AST is likely not matching the exact
498 // original AST, but the memory layout is preseved.
499 // After we collecting all fields in visitKnownMember, we have all fields in
500 // increasing offset order in m_fields. Since we are iterating in increase
501 // offset order, if the current offset is equal to m_start_offset, we insert
502 // it as direct field of top level record. If the current offset is greater
503 // than m_start_offset, we should be able to find a field in end_offset_map
504 // whose end offset is less than or equal to current offset. (if not, it might
505 // be missing field info. We will ignore the field in this case. e.g. Field A
506 // starts at 0 with size 4 bytes, and Field B starts at 2 with size 4 bytes.
507 // Normally, there must be something which ends at/before 2.) Then we will
508 // append current field to the end of parent record. If parent is struct, we
509 // can just grow it. If parent is a field, it's a field inside an union. We
510 // convert it into an anonymous struct containing old field and new field.
511
512 // The end offset to a vector of field/struct that ends at the offset.
513 std::map<uint64_t, std::vector<Member *>> end_offset_map;
514 auto is_last_end_offset = [&](auto it) {
515 return it != end_offset_map.end() && ++it == end_offset_map.end();
516 };
517
518 for (auto &pair : fields_map) {
519 uint64_t offset = pair.first;
520 auto &fields = pair.second;
521 assert(offset >= start_offset);
522 Member *parent = &record;
523 if (offset > start_offset) {
524 // Find the field with largest end offset that is <= offset. If it's less
525 // than offset, it indicates there are padding bytes between end offset
526 // and offset.
527 assert(!end_offset_map.empty());
528 auto iter = end_offset_map.lower_bound(offset);
529 if (iter == end_offset_map.end())
530 --iter;
531 else if (iter->first > offset) {
532 if (iter == end_offset_map.begin())
533 continue;
534 --iter;
535 }
536 if (iter->second.empty())
537 continue;
538
539 // If the new fields come after the already added ones
540 // without overlap, go back to the root.
541 if (iter->first <= offset && is_last_end_offset(iter)) {
542 if (record.kind == Member::Struct) {
543 parent = &record;
544 } else {
545 assert(record.kind == Member::Union &&
546 "Current record must be a union");
547 assert(!record.fields.empty());
548 // For unions, append the field to the last struct
549 parent = record.fields.back().get();
550 }
551 } else {
552 parent = iter->second.back();
553 iter->second.pop_back();
554 }
555 }
556 // If it's a field, then the field is inside a union, so we can safely
557 // increase its size by converting it to a struct to hold multiple fields.
558 if (parent->kind == Member::Field)
559 parent->ConvertToStruct();
560
561 if (fields.size() == 1) {
562 uint64_t end_offset = offset + fields.back()->bit_size;
563 parent->fields.push_back(std::move(fields.back()));
564 if (parent->kind == Member::Struct) {
565 end_offset_map[end_offset].push_back(parent);
566 } else {
567 assert(parent == &record &&
568 "If parent is union, it must be the top level record.");
569 end_offset_map[end_offset].push_back(parent->fields.back().get());
570 }
571 } else {
572 if (parent->kind == Member::Struct) {
573 parent->fields.push_back(std::make_unique<Member>(Member::Union));
574 parent = parent->fields.back().get();
575 parent->original_index = std::numeric_limits<uint32_t>::max();
576 parent->bit_offset = offset;
577 } else {
578 assert(parent == &record &&
579 "If parent is union, it must be the top level record.");
580 }
581 for (auto &field : fields) {
582 int64_t bit_size = field->bit_size;
583 // Use the lowest index of the union members.
584 parent->original_index =
585 std::min(parent->original_index, field->original_index);
586 parent->fields.push_back(std::move(field));
587 end_offset_map[offset + bit_size].push_back(
588 parent->fields.back().get());
589 }
590 }
591 }
592
593 record.RestoreOriginalOrder();
594}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
llvm::Error Error
void SetUserID(lldb::user_id_t user_id)
void SetIsDynamicCXXType(std::optional< bool > b)
Generic representation of a type in a programming language.
lldb::BasicType GetBasicTypeEnumeration() const
ConstString GetTypeName(bool BaseOnly=false) const
CompilerType CreateTypedef(const char *name, const CompilerDeclContext &decl_ctx, uint32_t payload) const
Create a typedef to this type using "name" as the name of the typedef this type is valid and the type...
A TypeSystem implementation based on Clang.
static void SetFloatingInitializerForVariable(clang::VarDecl *var, const llvm::APFloat &init_value)
Initializes a variable with a floating point value.
static void SetIntegerInitializerForVariable(clang::VarDecl *var, const llvm::APInt &init_value)
Initializes a variable with an integer value.
static clang::VarDecl * AddVariableToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &var_type)
static void BuildIndirectFields(const CompilerType &type)
static clang::CXXRecordDecl * GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type)
static bool CompleteTagDeclarationDefinition(const CompilerType &type)
static bool StartTagDeclarationDefinition(const CompilerType &type)
static clang::FieldDecl * AddFieldToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &field_type, uint32_t bitfield_bit_size)
static clang::EnumDecl * GetAsEnumDecl(const CompilerType &type)
static void RequireCompleteType(CompilerType type)
Complete a type from debug info, or mark it as forcefully completed if there is no definition of the ...
PdbIndex - Lazy access to the important parts of a PDB file.
Definition PdbIndex.h:47
llvm::DenseMap< lldb::opaque_compiler_type_t, llvm::SmallSet< std::pair< llvm::StringRef, CompilerType >, 8 > > & m_cxx_record_map
llvm::Error visitMemberEnd(llvm::codeview::CVMemberRecord &Record) override
ClangASTImporter::LayoutInfo m_layout
llvm::DenseMap< clang::Decl *, DeclStatus > & m_decl_to_status
uint64_t AddMember(TypeSystemClang &clang, Member *field, uint64_t bit_offset, CompilerType parent_ct, ClangASTImporter::LayoutInfo &parent_layout, clang::DeclContext *decl_ctx)
UdtRecordCompleter(PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl, PdbAstBuilderClang &ast_builder, PdbIndex &index, llvm::DenseMap< clang::Decl *, DeclStatus > &decl_to_status, llvm::DenseMap< lldb::opaque_compiler_type_t, llvm::SmallSet< std::pair< llvm::StringRef, CompilerType >, 8 > > &cxx_record_map)
clang::QualType AddBaseClassForTypeIndex(llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access, std::optional< uint64_t > vtable_idx=std::optional< uint64_t >())
uint32_t m_member_index
Index of the current member.
void AddMethod(llvm::StringRef name, llvm::codeview::TypeIndex type_idx, llvm::codeview::MethodOptions options, llvm::codeview::MemberAttributes attrs)
llvm::StringRef DropNameScope(llvm::StringRef name)
Definition PdbUtil.cpp:602
lldb::AccessType TranslateMemberAccess(llvm::codeview::MemberAccess access)
size_t GetSizeOfType(PdbTypeSymId id, llvm::pdb::TpiStream &tpi)
Definition PdbUtil.cpp:1150
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
void * opaque_compiler_type_t
Definition lldb-types.h:91
BasicType
Basic types enumeration for the public API SBType::GetBasicType().
@ eBasicTypeLongDouble
@ eLanguageTypeC_plus_plus
ISO C++:1998.
llvm::DenseMap< const clang::FieldDecl *, uint64_t > field_offsets
llvm::codeview::TypeIndex index
Definition PdbSymUid.h:73
enum lldb_private::npdb::UdtRecordCompleter::Member::Kind kind
uint32_t original_index
Index of the member inside the LF_FIELDLIST.
std::map< uint64_t, llvm::SmallVector< MemberUP, 1 > > fields_map
void CollectMember(llvm::StringRef name, uint64_t offset, uint64_t field_size, clang::QualType qt, lldb::AccessType access, uint64_t bitfield_width, uint32_t member_index)