1 | //===-- PDBASTParser.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 "PDBASTParser.h" |
10 | |
11 | #include "SymbolFilePDB.h" |
12 | |
13 | #include "clang/AST/CharUnits.h" |
14 | #include "clang/AST/Decl.h" |
15 | #include "clang/AST/DeclCXX.h" |
16 | |
17 | #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" |
18 | #include "Plugins/ExpressionParser/Clang/ClangUtil.h" |
19 | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
20 | #include "lldb/Core/Declaration.h" |
21 | #include "lldb/Core/Module.h" |
22 | #include "lldb/Symbol/SymbolFile.h" |
23 | #include "lldb/Symbol/TypeMap.h" |
24 | #include "lldb/Symbol/TypeSystem.h" |
25 | #include "lldb/Utility/LLDBLog.h" |
26 | #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" |
27 | #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" |
28 | #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" |
29 | #include "llvm/DebugInfo/PDB/PDBSymbol.h" |
30 | #include "llvm/DebugInfo/PDB/PDBSymbolData.h" |
31 | #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" |
32 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" |
33 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" |
34 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" |
35 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" |
36 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" |
37 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" |
38 | #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" |
39 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" |
40 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" |
41 | |
42 | #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" |
43 | #include <optional> |
44 | |
45 | using namespace lldb; |
46 | using namespace lldb_private; |
47 | using namespace llvm::pdb; |
48 | |
49 | static int TranslateUdtKind(PDB_UdtType pdb_kind) { |
50 | switch (pdb_kind) { |
51 | case PDB_UdtType::Class: |
52 | return llvm::to_underlying(E: clang::TagTypeKind::Class); |
53 | case PDB_UdtType::Struct: |
54 | return llvm::to_underlying(E: clang::TagTypeKind::Struct); |
55 | case PDB_UdtType::Union: |
56 | return llvm::to_underlying(E: clang::TagTypeKind::Union); |
57 | case PDB_UdtType::Interface: |
58 | return llvm::to_underlying(E: clang::TagTypeKind::Interface); |
59 | } |
60 | llvm_unreachable("unsuported PDB UDT type" ); |
61 | } |
62 | |
63 | static lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) { |
64 | switch (type) { |
65 | case PDB_BuiltinType::Float: |
66 | return lldb::eEncodingIEEE754; |
67 | case PDB_BuiltinType::Int: |
68 | case PDB_BuiltinType::Long: |
69 | case PDB_BuiltinType::Char: |
70 | return lldb::eEncodingSint; |
71 | case PDB_BuiltinType::Bool: |
72 | case PDB_BuiltinType::Char16: |
73 | case PDB_BuiltinType::Char32: |
74 | case PDB_BuiltinType::UInt: |
75 | case PDB_BuiltinType::ULong: |
76 | case PDB_BuiltinType::HResult: |
77 | case PDB_BuiltinType::WCharT: |
78 | return lldb::eEncodingUint; |
79 | default: |
80 | return lldb::eEncodingInvalid; |
81 | } |
82 | } |
83 | |
84 | static lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) { |
85 | switch (type) { |
86 | case PDB_VariantType::Int8: |
87 | case PDB_VariantType::Int16: |
88 | case PDB_VariantType::Int32: |
89 | case PDB_VariantType::Int64: |
90 | return lldb::eEncodingSint; |
91 | |
92 | case PDB_VariantType::UInt8: |
93 | case PDB_VariantType::UInt16: |
94 | case PDB_VariantType::UInt32: |
95 | case PDB_VariantType::UInt64: |
96 | return lldb::eEncodingUint; |
97 | |
98 | default: |
99 | break; |
100 | } |
101 | |
102 | return lldb::eEncodingSint; |
103 | } |
104 | |
105 | static CompilerType |
106 | GetBuiltinTypeForPDBEncodingAndBitSize(TypeSystemClang &clang_ast, |
107 | const PDBSymbolTypeBuiltin &pdb_type, |
108 | Encoding encoding, uint32_t width) { |
109 | clang::ASTContext &ast = clang_ast.getASTContext(); |
110 | |
111 | switch (pdb_type.getBuiltinType()) { |
112 | default: |
113 | break; |
114 | case PDB_BuiltinType::None: |
115 | return CompilerType(); |
116 | case PDB_BuiltinType::Void: |
117 | return clang_ast.GetBasicType(type: eBasicTypeVoid); |
118 | case PDB_BuiltinType::Char: |
119 | return clang_ast.GetBasicType(type: eBasicTypeChar); |
120 | case PDB_BuiltinType::Bool: |
121 | return clang_ast.GetBasicType(type: eBasicTypeBool); |
122 | case PDB_BuiltinType::Long: |
123 | if (width == ast.getTypeSize(ast.LongTy)) |
124 | return CompilerType(clang_ast.weak_from_this(), |
125 | ast.LongTy.getAsOpaquePtr()); |
126 | if (width == ast.getTypeSize(ast.LongLongTy)) |
127 | return CompilerType(clang_ast.weak_from_this(), |
128 | ast.LongLongTy.getAsOpaquePtr()); |
129 | break; |
130 | case PDB_BuiltinType::ULong: |
131 | if (width == ast.getTypeSize(ast.UnsignedLongTy)) |
132 | return CompilerType(clang_ast.weak_from_this(), |
133 | ast.UnsignedLongTy.getAsOpaquePtr()); |
134 | if (width == ast.getTypeSize(ast.UnsignedLongLongTy)) |
135 | return CompilerType(clang_ast.weak_from_this(), |
136 | ast.UnsignedLongLongTy.getAsOpaquePtr()); |
137 | break; |
138 | case PDB_BuiltinType::WCharT: |
139 | if (width == ast.getTypeSize(ast.WCharTy)) |
140 | return CompilerType(clang_ast.weak_from_this(), |
141 | ast.WCharTy.getAsOpaquePtr()); |
142 | break; |
143 | case PDB_BuiltinType::Char16: |
144 | return CompilerType(clang_ast.weak_from_this(), |
145 | ast.Char16Ty.getAsOpaquePtr()); |
146 | case PDB_BuiltinType::Char32: |
147 | return CompilerType(clang_ast.weak_from_this(), |
148 | ast.Char32Ty.getAsOpaquePtr()); |
149 | case PDB_BuiltinType::Float: |
150 | // Note: types `long double` and `double` have same bit size in MSVC and |
151 | // there is no information in the PDB to distinguish them. So when falling |
152 | // back to default search, the compiler type of `long double` will be |
153 | // represented by the one generated for `double`. |
154 | break; |
155 | } |
156 | // If there is no match on PDB_BuiltinType, fall back to default search by |
157 | // encoding and width only |
158 | return clang_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bit_size: width); |
159 | } |
160 | |
161 | static ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type, |
162 | CompilerType &compiler_type) { |
163 | PDB_BuiltinType kind = pdb_type.getBuiltinType(); |
164 | switch (kind) { |
165 | default: |
166 | break; |
167 | case PDB_BuiltinType::Currency: |
168 | return ConstString("CURRENCY" ); |
169 | case PDB_BuiltinType::Date: |
170 | return ConstString("DATE" ); |
171 | case PDB_BuiltinType::Variant: |
172 | return ConstString("VARIANT" ); |
173 | case PDB_BuiltinType::Complex: |
174 | return ConstString("complex" ); |
175 | case PDB_BuiltinType::Bitfield: |
176 | return ConstString("bitfield" ); |
177 | case PDB_BuiltinType::BSTR: |
178 | return ConstString("BSTR" ); |
179 | case PDB_BuiltinType::HResult: |
180 | return ConstString("HRESULT" ); |
181 | case PDB_BuiltinType::BCD: |
182 | return ConstString("BCD" ); |
183 | case PDB_BuiltinType::Char16: |
184 | return ConstString("char16_t" ); |
185 | case PDB_BuiltinType::Char32: |
186 | return ConstString("char32_t" ); |
187 | case PDB_BuiltinType::None: |
188 | return ConstString("..." ); |
189 | } |
190 | return compiler_type.GetTypeName(); |
191 | } |
192 | |
193 | static bool AddSourceInfoToDecl(const PDBSymbol &symbol, Declaration &decl) { |
194 | auto &raw_sym = symbol.getRawSymbol(); |
195 | auto first_line_up = raw_sym.getSrcLineOnTypeDefn(); |
196 | |
197 | if (!first_line_up) { |
198 | auto lines_up = symbol.getSession().findLineNumbersByAddress( |
199 | Address: raw_sym.getVirtualAddress(), Length: raw_sym.getLength()); |
200 | if (!lines_up) |
201 | return false; |
202 | first_line_up = lines_up->getNext(); |
203 | if (!first_line_up) |
204 | return false; |
205 | } |
206 | uint32_t src_file_id = first_line_up->getSourceFileId(); |
207 | auto src_file_up = symbol.getSession().getSourceFileById(FileId: src_file_id); |
208 | if (!src_file_up) |
209 | return false; |
210 | |
211 | FileSpec spec(src_file_up->getFileName()); |
212 | decl.SetFile(spec); |
213 | decl.SetColumn(first_line_up->getColumnNumber()); |
214 | decl.SetLine(first_line_up->getLineNumber()); |
215 | return true; |
216 | } |
217 | |
218 | static AccessType TranslateMemberAccess(PDB_MemberAccess access) { |
219 | switch (access) { |
220 | case PDB_MemberAccess::Private: |
221 | return eAccessPrivate; |
222 | case PDB_MemberAccess::Protected: |
223 | return eAccessProtected; |
224 | case PDB_MemberAccess::Public: |
225 | return eAccessPublic; |
226 | } |
227 | return eAccessNone; |
228 | } |
229 | |
230 | static AccessType GetDefaultAccessibilityForUdtKind(PDB_UdtType udt_kind) { |
231 | switch (udt_kind) { |
232 | case PDB_UdtType::Struct: |
233 | case PDB_UdtType::Union: |
234 | return eAccessPublic; |
235 | case PDB_UdtType::Class: |
236 | case PDB_UdtType::Interface: |
237 | return eAccessPrivate; |
238 | } |
239 | llvm_unreachable("unsupported PDB UDT type" ); |
240 | } |
241 | |
242 | static AccessType GetAccessibilityForUdt(const PDBSymbolTypeUDT &udt) { |
243 | AccessType access = TranslateMemberAccess(access: udt.getAccess()); |
244 | if (access != lldb::eAccessNone || !udt.isNested()) |
245 | return access; |
246 | |
247 | auto parent = udt.getClassParent(); |
248 | if (!parent) |
249 | return lldb::eAccessNone; |
250 | |
251 | auto parent_udt = llvm::dyn_cast<PDBSymbolTypeUDT>(Val: parent.get()); |
252 | if (!parent_udt) |
253 | return lldb::eAccessNone; |
254 | |
255 | return GetDefaultAccessibilityForUdtKind(udt_kind: parent_udt->getUdtKind()); |
256 | } |
257 | |
258 | static clang::MSInheritanceAttr::Spelling |
259 | GetMSInheritance(const PDBSymbolTypeUDT &udt) { |
260 | int base_count = 0; |
261 | bool has_virtual = false; |
262 | |
263 | auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>(); |
264 | if (bases_enum) { |
265 | while (auto base = bases_enum->getNext()) { |
266 | base_count++; |
267 | has_virtual |= base->isVirtualBaseClass(); |
268 | } |
269 | } |
270 | |
271 | if (has_virtual) |
272 | return clang::MSInheritanceAttr::Keyword_virtual_inheritance; |
273 | if (base_count > 1) |
274 | return clang::MSInheritanceAttr::Keyword_multiple_inheritance; |
275 | return clang::MSInheritanceAttr::Keyword_single_inheritance; |
276 | } |
277 | |
278 | static std::unique_ptr<llvm::pdb::PDBSymbol> |
279 | GetClassOrFunctionParent(const llvm::pdb::PDBSymbol &symbol) { |
280 | const IPDBSession &session = symbol.getSession(); |
281 | const IPDBRawSymbol &raw = symbol.getRawSymbol(); |
282 | auto tag = symbol.getSymTag(); |
283 | |
284 | // For items that are nested inside of a class, return the class that it is |
285 | // nested inside of. |
286 | // Note that only certain items can be nested inside of classes. |
287 | switch (tag) { |
288 | case PDB_SymType::Function: |
289 | case PDB_SymType::Data: |
290 | case PDB_SymType::UDT: |
291 | case PDB_SymType::Enum: |
292 | case PDB_SymType::FunctionSig: |
293 | case PDB_SymType::Typedef: |
294 | case PDB_SymType::BaseClass: |
295 | case PDB_SymType::VTable: { |
296 | auto class_parent_id = raw.getClassParentId(); |
297 | if (auto class_parent = session.getSymbolById(SymbolId: class_parent_id)) |
298 | return class_parent; |
299 | break; |
300 | } |
301 | default: |
302 | break; |
303 | } |
304 | |
305 | // Otherwise, if it is nested inside of a function, return the function. |
306 | // Note that only certain items can be nested inside of functions. |
307 | switch (tag) { |
308 | case PDB_SymType::Block: |
309 | case PDB_SymType::Data: { |
310 | auto lexical_parent_id = raw.getLexicalParentId(); |
311 | auto lexical_parent = session.getSymbolById(SymbolId: lexical_parent_id); |
312 | if (!lexical_parent) |
313 | return nullptr; |
314 | |
315 | auto lexical_parent_tag = lexical_parent->getSymTag(); |
316 | if (lexical_parent_tag == PDB_SymType::Function) |
317 | return lexical_parent; |
318 | if (lexical_parent_tag == PDB_SymType::Exe) |
319 | return nullptr; |
320 | |
321 | return GetClassOrFunctionParent(symbol: *lexical_parent); |
322 | } |
323 | default: |
324 | return nullptr; |
325 | } |
326 | } |
327 | |
328 | static clang::NamedDecl * |
329 | GetDeclFromContextByName(const clang::ASTContext &ast, |
330 | const clang::DeclContext &decl_context, |
331 | llvm::StringRef name) { |
332 | clang::IdentifierInfo &ident = ast.Idents.get(Name: name); |
333 | clang::DeclarationName decl_name = ast.DeclarationNames.getIdentifier(ID: &ident); |
334 | clang::DeclContext::lookup_result result = decl_context.lookup(Name: decl_name); |
335 | if (result.empty()) |
336 | return nullptr; |
337 | |
338 | return *result.begin(); |
339 | } |
340 | |
341 | static bool IsAnonymousNamespaceName(llvm::StringRef name) { |
342 | return name == "`anonymous namespace'" || name == "`anonymous-namespace'" ; |
343 | } |
344 | |
345 | static clang::CallingConv TranslateCallingConvention(PDB_CallingConv pdb_cc) { |
346 | switch (pdb_cc) { |
347 | case llvm::codeview::CallingConvention::NearC: |
348 | return clang::CC_C; |
349 | case llvm::codeview::CallingConvention::NearStdCall: |
350 | return clang::CC_X86StdCall; |
351 | case llvm::codeview::CallingConvention::NearFast: |
352 | return clang::CC_X86FastCall; |
353 | case llvm::codeview::CallingConvention::ThisCall: |
354 | return clang::CC_X86ThisCall; |
355 | case llvm::codeview::CallingConvention::NearVector: |
356 | return clang::CC_X86VectorCall; |
357 | case llvm::codeview::CallingConvention::NearPascal: |
358 | return clang::CC_X86Pascal; |
359 | default: |
360 | assert(false && "Unknown calling convention" ); |
361 | return clang::CC_C; |
362 | } |
363 | } |
364 | |
365 | PDBASTParser::PDBASTParser(lldb_private::TypeSystemClang &ast) : m_ast(ast) {} |
366 | |
367 | PDBASTParser::~PDBASTParser() = default; |
368 | |
369 | // DebugInfoASTParser interface |
370 | |
371 | lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { |
372 | Declaration decl; |
373 | switch (type.getSymTag()) { |
374 | case PDB_SymType::BaseClass: { |
375 | auto symbol_file = m_ast.GetSymbolFile(); |
376 | if (!symbol_file) |
377 | return nullptr; |
378 | |
379 | auto ty = symbol_file->ResolveTypeUID(type_uid: type.getRawSymbol().getTypeId()); |
380 | return ty ? ty->shared_from_this() : nullptr; |
381 | } break; |
382 | case PDB_SymType::UDT: { |
383 | auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(Val: &type); |
384 | assert(udt); |
385 | |
386 | // Note that, unnamed UDT being typedef-ed is generated as a UDT symbol |
387 | // other than a Typedef symbol in PDB. For example, |
388 | // typedef union { short Row; short Col; } Union; |
389 | // is generated as a named UDT in PDB: |
390 | // union Union { short Row; short Col; } |
391 | // Such symbols will be handled here. |
392 | |
393 | // Some UDT with trival ctor has zero length. Just ignore. |
394 | if (udt->getLength() == 0) |
395 | return nullptr; |
396 | |
397 | // Ignore unnamed-tag UDTs. |
398 | std::string name = |
399 | std::string(MSVCUndecoratedNameParser::DropScope(name: udt->getName())); |
400 | if (name.empty()) |
401 | return nullptr; |
402 | |
403 | auto decl_context = GetDeclContextContainingSymbol(symbol: type); |
404 | |
405 | // Check if such an UDT already exists in the current context. |
406 | // This may occur with const or volatile types. There are separate type |
407 | // symbols in PDB for types with const or volatile modifiers, but we need |
408 | // to create only one declaration for them all. |
409 | Type::ResolveState type_resolve_state; |
410 | CompilerType clang_type = |
411 | m_ast.GetTypeForIdentifier<clang::CXXRecordDecl>(type_name: name, decl_context); |
412 | if (!clang_type.IsValid()) { |
413 | auto access = GetAccessibilityForUdt(udt: *udt); |
414 | |
415 | auto tag_type_kind = TranslateUdtKind(pdb_kind: udt->getUdtKind()); |
416 | |
417 | ClangASTMetadata metadata; |
418 | metadata.SetUserID(type.getSymIndexId()); |
419 | metadata.SetIsDynamicCXXType(false); |
420 | |
421 | clang_type = m_ast.CreateRecordType( |
422 | decl_ctx: decl_context, owning_module: OptionalClangModuleID(), access_type: access, name, kind: tag_type_kind, |
423 | language: lldb::eLanguageTypeC_plus_plus, metadata: &metadata); |
424 | assert(clang_type.IsValid()); |
425 | |
426 | auto record_decl = |
427 | m_ast.GetAsCXXRecordDecl(type: clang_type.GetOpaqueQualType()); |
428 | assert(record_decl); |
429 | m_uid_to_decl[type.getSymIndexId()] = record_decl; |
430 | |
431 | auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit( |
432 | m_ast.getASTContext(), GetMSInheritance(*udt)); |
433 | record_decl->addAttr(A: inheritance_attr); |
434 | |
435 | TypeSystemClang::StartTagDeclarationDefinition(type: clang_type); |
436 | |
437 | auto children = udt->findAllChildren(); |
438 | if (!children || children->getChildCount() == 0) { |
439 | // PDB does not have symbol of forwarder. We assume we get an udt w/o |
440 | // any fields. Just complete it at this point. |
441 | TypeSystemClang::CompleteTagDeclarationDefinition(type: clang_type); |
442 | |
443 | TypeSystemClang::SetHasExternalStorage(type: clang_type.GetOpaqueQualType(), |
444 | has_extern: false); |
445 | |
446 | type_resolve_state = Type::ResolveState::Full; |
447 | } else { |
448 | // Add the type to the forward declarations. It will help us to avoid |
449 | // an endless recursion in CompleteTypeFromUdt function. |
450 | m_forward_decl_to_uid[record_decl] = type.getSymIndexId(); |
451 | |
452 | TypeSystemClang::SetHasExternalStorage(type: clang_type.GetOpaqueQualType(), |
453 | has_extern: true); |
454 | |
455 | type_resolve_state = Type::ResolveState::Forward; |
456 | } |
457 | } else |
458 | type_resolve_state = Type::ResolveState::Forward; |
459 | |
460 | if (udt->isConstType()) |
461 | clang_type = clang_type.AddConstModifier(); |
462 | |
463 | if (udt->isVolatileType()) |
464 | clang_type = clang_type.AddVolatileModifier(); |
465 | |
466 | AddSourceInfoToDecl(symbol: type, decl); |
467 | return m_ast.GetSymbolFile()->MakeType( |
468 | uid: type.getSymIndexId(), name: ConstString(name), byte_size: udt->getLength(), context: nullptr, |
469 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, compiler_qual_type: clang_type, |
470 | compiler_type_resolve_state: type_resolve_state); |
471 | } break; |
472 | case PDB_SymType::Enum: { |
473 | auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(Val: &type); |
474 | assert(enum_type); |
475 | |
476 | std::string name = |
477 | std::string(MSVCUndecoratedNameParser::DropScope(name: enum_type->getName())); |
478 | auto decl_context = GetDeclContextContainingSymbol(symbol: type); |
479 | uint64_t bytes = enum_type->getLength(); |
480 | |
481 | // Check if such an enum already exists in the current context |
482 | CompilerType ast_enum = |
483 | m_ast.GetTypeForIdentifier<clang::EnumDecl>(type_name: name, decl_context); |
484 | if (!ast_enum.IsValid()) { |
485 | auto underlying_type_up = enum_type->getUnderlyingType(); |
486 | if (!underlying_type_up) |
487 | return nullptr; |
488 | |
489 | lldb::Encoding encoding = |
490 | TranslateBuiltinEncoding(type: underlying_type_up->getBuiltinType()); |
491 | // FIXME: Type of underlying builtin is always `Int`. We correct it with |
492 | // the very first enumerator's encoding if any. |
493 | auto first_child = enum_type->findOneChild<PDBSymbolData>(); |
494 | if (first_child) |
495 | encoding = TranslateEnumEncoding(type: first_child->getValue().Type); |
496 | |
497 | CompilerType builtin_type; |
498 | if (bytes > 0) |
499 | builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize( |
500 | clang_ast&: m_ast, pdb_type: *underlying_type_up, encoding, width: bytes * 8); |
501 | else |
502 | builtin_type = m_ast.GetBasicType(type: eBasicTypeInt); |
503 | |
504 | // FIXME: PDB does not have information about scoped enumeration (Enum |
505 | // Class). Set it false for now. |
506 | bool isScoped = false; |
507 | |
508 | ast_enum = m_ast.CreateEnumerationType(name, decl_ctx: decl_context, |
509 | owning_module: OptionalClangModuleID(), decl, |
510 | integer_qual_type: builtin_type, is_scoped: isScoped); |
511 | |
512 | auto enum_decl = TypeSystemClang::GetAsEnumDecl(type: ast_enum); |
513 | assert(enum_decl); |
514 | m_uid_to_decl[type.getSymIndexId()] = enum_decl; |
515 | |
516 | auto enum_values = enum_type->findAllChildren<PDBSymbolData>(); |
517 | if (enum_values) { |
518 | while (auto enum_value = enum_values->getNext()) { |
519 | if (enum_value->getDataKind() != PDB_DataKind::Constant) |
520 | continue; |
521 | AddEnumValue(enum_type: ast_enum, data: *enum_value); |
522 | } |
523 | } |
524 | |
525 | if (TypeSystemClang::StartTagDeclarationDefinition(type: ast_enum)) |
526 | TypeSystemClang::CompleteTagDeclarationDefinition(type: ast_enum); |
527 | } |
528 | |
529 | if (enum_type->isConstType()) |
530 | ast_enum = ast_enum.AddConstModifier(); |
531 | |
532 | if (enum_type->isVolatileType()) |
533 | ast_enum = ast_enum.AddVolatileModifier(); |
534 | |
535 | AddSourceInfoToDecl(symbol: type, decl); |
536 | return m_ast.GetSymbolFile()->MakeType( |
537 | uid: type.getSymIndexId(), name: ConstString(name), byte_size: bytes, context: nullptr, |
538 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, compiler_qual_type: ast_enum, |
539 | compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
540 | } break; |
541 | case PDB_SymType::Typedef: { |
542 | auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(Val: &type); |
543 | assert(type_def); |
544 | |
545 | SymbolFile *symbol_file = m_ast.GetSymbolFile(); |
546 | if (!symbol_file) |
547 | return nullptr; |
548 | |
549 | lldb_private::Type *target_type = |
550 | symbol_file->ResolveTypeUID(type_uid: type_def->getTypeId()); |
551 | if (!target_type) |
552 | return nullptr; |
553 | |
554 | std::string name = |
555 | std::string(MSVCUndecoratedNameParser::DropScope(name: type_def->getName())); |
556 | auto decl_ctx = GetDeclContextContainingSymbol(symbol: type); |
557 | |
558 | // Check if such a typedef already exists in the current context |
559 | CompilerType ast_typedef = |
560 | m_ast.GetTypeForIdentifier<clang::TypedefNameDecl>(type_name: name, decl_context: decl_ctx); |
561 | if (!ast_typedef.IsValid()) { |
562 | CompilerType target_ast_type = target_type->GetFullCompilerType(); |
563 | |
564 | ast_typedef = target_ast_type.CreateTypedef( |
565 | name: name.c_str(), decl_ctx: m_ast.CreateDeclContext(ctx: decl_ctx), payload: 0); |
566 | if (!ast_typedef) |
567 | return nullptr; |
568 | |
569 | auto typedef_decl = TypeSystemClang::GetAsTypedefDecl(type: ast_typedef); |
570 | assert(typedef_decl); |
571 | m_uid_to_decl[type.getSymIndexId()] = typedef_decl; |
572 | } |
573 | |
574 | if (type_def->isConstType()) |
575 | ast_typedef = ast_typedef.AddConstModifier(); |
576 | |
577 | if (type_def->isVolatileType()) |
578 | ast_typedef = ast_typedef.AddVolatileModifier(); |
579 | |
580 | AddSourceInfoToDecl(symbol: type, decl); |
581 | std::optional<uint64_t> size; |
582 | if (type_def->getLength()) |
583 | size = type_def->getLength(); |
584 | return m_ast.GetSymbolFile()->MakeType( |
585 | uid: type_def->getSymIndexId(), name: ConstString(name), byte_size: size, context: nullptr, |
586 | encoding_uid: target_type->GetID(), encoding_uid_type: lldb_private::Type::eEncodingIsTypedefUID, decl, |
587 | compiler_qual_type: ast_typedef, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
588 | } break; |
589 | case PDB_SymType::Function: |
590 | case PDB_SymType::FunctionSig: { |
591 | std::string name; |
592 | PDBSymbolTypeFunctionSig *func_sig = nullptr; |
593 | if (auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(Val: &type)) { |
594 | if (pdb_func->isCompilerGenerated()) |
595 | return nullptr; |
596 | |
597 | auto sig = pdb_func->getSignature(); |
598 | if (!sig) |
599 | return nullptr; |
600 | func_sig = sig.release(); |
601 | // Function type is named. |
602 | name = std::string( |
603 | MSVCUndecoratedNameParser::DropScope(name: pdb_func->getName())); |
604 | } else if (auto pdb_func_sig = |
605 | llvm::dyn_cast<PDBSymbolTypeFunctionSig>(Val: &type)) { |
606 | func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig); |
607 | } else |
608 | llvm_unreachable("Unexpected PDB symbol!" ); |
609 | |
610 | auto arg_enum = func_sig->getArguments(); |
611 | uint32_t num_args = arg_enum->getChildCount(); |
612 | std::vector<CompilerType> arg_list; |
613 | |
614 | bool is_variadic = func_sig->isCVarArgs(); |
615 | // Drop last variadic argument. |
616 | if (is_variadic) |
617 | --num_args; |
618 | for (uint32_t arg_idx = 0; arg_idx < num_args; arg_idx++) { |
619 | auto arg = arg_enum->getChildAtIndex(Index: arg_idx); |
620 | if (!arg) |
621 | break; |
622 | |
623 | SymbolFile *symbol_file = m_ast.GetSymbolFile(); |
624 | if (!symbol_file) |
625 | return nullptr; |
626 | |
627 | lldb_private::Type *arg_type = |
628 | symbol_file->ResolveTypeUID(type_uid: arg->getSymIndexId()); |
629 | // If there's some error looking up one of the dependent types of this |
630 | // function signature, bail. |
631 | if (!arg_type) |
632 | return nullptr; |
633 | CompilerType arg_ast_type = arg_type->GetFullCompilerType(); |
634 | arg_list.push_back(x: arg_ast_type); |
635 | } |
636 | lldbassert(arg_list.size() <= num_args); |
637 | |
638 | auto pdb_return_type = func_sig->getReturnType(); |
639 | SymbolFile *symbol_file = m_ast.GetSymbolFile(); |
640 | if (!symbol_file) |
641 | return nullptr; |
642 | |
643 | lldb_private::Type *return_type = |
644 | symbol_file->ResolveTypeUID(type_uid: pdb_return_type->getSymIndexId()); |
645 | // If there's some error looking up one of the dependent types of this |
646 | // function signature, bail. |
647 | if (!return_type) |
648 | return nullptr; |
649 | CompilerType return_ast_type = return_type->GetFullCompilerType(); |
650 | uint32_t type_quals = 0; |
651 | if (func_sig->isConstType()) |
652 | type_quals |= clang::Qualifiers::Const; |
653 | if (func_sig->isVolatileType()) |
654 | type_quals |= clang::Qualifiers::Volatile; |
655 | auto cc = TranslateCallingConvention(pdb_cc: func_sig->getCallingConvention()); |
656 | CompilerType func_sig_ast_type = |
657 | m_ast.CreateFunctionType(result_type: return_ast_type, args: arg_list.data(), |
658 | num_args: arg_list.size(), is_variadic, type_quals, cc); |
659 | |
660 | AddSourceInfoToDecl(symbol: type, decl); |
661 | return m_ast.GetSymbolFile()->MakeType( |
662 | uid: type.getSymIndexId(), name: ConstString(name), byte_size: std::nullopt, context: nullptr, |
663 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
664 | compiler_qual_type: func_sig_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
665 | } break; |
666 | case PDB_SymType::ArrayType: { |
667 | auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(Val: &type); |
668 | assert(array_type); |
669 | uint32_t num_elements = array_type->getCount(); |
670 | uint32_t element_uid = array_type->getElementTypeId(); |
671 | std::optional<uint64_t> bytes; |
672 | if (uint64_t size = array_type->getLength()) |
673 | bytes = size; |
674 | |
675 | SymbolFile *symbol_file = m_ast.GetSymbolFile(); |
676 | if (!symbol_file) |
677 | return nullptr; |
678 | |
679 | // If array rank > 0, PDB gives the element type at N=0. So element type |
680 | // will parsed in the order N=0, N=1,..., N=rank sequentially. |
681 | lldb_private::Type *element_type = symbol_file->ResolveTypeUID(type_uid: element_uid); |
682 | if (!element_type) |
683 | return nullptr; |
684 | |
685 | CompilerType element_ast_type = element_type->GetForwardCompilerType(); |
686 | // If element type is UDT, it needs to be complete. |
687 | if (TypeSystemClang::IsCXXClassType(type: element_ast_type) && |
688 | !element_ast_type.GetCompleteType()) { |
689 | if (TypeSystemClang::StartTagDeclarationDefinition(type: element_ast_type)) { |
690 | TypeSystemClang::CompleteTagDeclarationDefinition(type: element_ast_type); |
691 | } else { |
692 | // We are not able to start definition. |
693 | return nullptr; |
694 | } |
695 | } |
696 | CompilerType array_ast_type = m_ast.CreateArrayType( |
697 | element_type: element_ast_type, element_count: num_elements, /*is_gnu_vector*/ is_vector: false); |
698 | TypeSP type_sp = m_ast.GetSymbolFile()->MakeType( |
699 | uid: array_type->getSymIndexId(), name: ConstString(), byte_size: bytes, context: nullptr, |
700 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
701 | compiler_qual_type: array_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
702 | type_sp->SetEncodingType(element_type); |
703 | return type_sp; |
704 | } break; |
705 | case PDB_SymType::BuiltinType: { |
706 | auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(Val: &type); |
707 | assert(builtin_type); |
708 | PDB_BuiltinType builtin_kind = builtin_type->getBuiltinType(); |
709 | if (builtin_kind == PDB_BuiltinType::None) |
710 | return nullptr; |
711 | |
712 | std::optional<uint64_t> bytes; |
713 | if (uint64_t size = builtin_type->getLength()) |
714 | bytes = size; |
715 | Encoding encoding = TranslateBuiltinEncoding(type: builtin_kind); |
716 | CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize( |
717 | clang_ast&: m_ast, pdb_type: *builtin_type, encoding, width: bytes.value_or(u: 0) * 8); |
718 | |
719 | if (builtin_type->isConstType()) |
720 | builtin_ast_type = builtin_ast_type.AddConstModifier(); |
721 | |
722 | if (builtin_type->isVolatileType()) |
723 | builtin_ast_type = builtin_ast_type.AddVolatileModifier(); |
724 | |
725 | auto type_name = GetPDBBuiltinTypeName(pdb_type: *builtin_type, compiler_type&: builtin_ast_type); |
726 | |
727 | return m_ast.GetSymbolFile()->MakeType( |
728 | uid: builtin_type->getSymIndexId(), name: type_name, byte_size: bytes, context: nullptr, |
729 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
730 | compiler_qual_type: builtin_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
731 | } break; |
732 | case PDB_SymType::PointerType: { |
733 | auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(Val: &type); |
734 | assert(pointer_type); |
735 | |
736 | SymbolFile *symbol_file = m_ast.GetSymbolFile(); |
737 | if (!symbol_file) |
738 | return nullptr; |
739 | |
740 | Type *pointee_type = symbol_file->ResolveTypeUID( |
741 | type_uid: pointer_type->getPointeeType()->getSymIndexId()); |
742 | if (!pointee_type) |
743 | return nullptr; |
744 | |
745 | if (pointer_type->isPointerToDataMember() || |
746 | pointer_type->isPointerToMemberFunction()) { |
747 | auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId(); |
748 | auto class_parent_type = symbol_file->ResolveTypeUID(type_uid: class_parent_uid); |
749 | assert(class_parent_type); |
750 | |
751 | CompilerType pointer_ast_type; |
752 | pointer_ast_type = TypeSystemClang::CreateMemberPointerType( |
753 | type: class_parent_type->GetLayoutCompilerType(), |
754 | pointee_type: pointee_type->GetForwardCompilerType()); |
755 | assert(pointer_ast_type); |
756 | |
757 | return m_ast.GetSymbolFile()->MakeType( |
758 | uid: pointer_type->getSymIndexId(), name: ConstString(), |
759 | byte_size: pointer_type->getLength(), context: nullptr, LLDB_INVALID_UID, |
760 | encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, compiler_qual_type: pointer_ast_type, |
761 | compiler_type_resolve_state: lldb_private::Type::ResolveState::Forward); |
762 | } |
763 | |
764 | CompilerType pointer_ast_type; |
765 | pointer_ast_type = pointee_type->GetFullCompilerType(); |
766 | if (pointer_type->isReference()) |
767 | pointer_ast_type = pointer_ast_type.GetLValueReferenceType(); |
768 | else if (pointer_type->isRValueReference()) |
769 | pointer_ast_type = pointer_ast_type.GetRValueReferenceType(); |
770 | else |
771 | pointer_ast_type = pointer_ast_type.GetPointerType(); |
772 | |
773 | if (pointer_type->isConstType()) |
774 | pointer_ast_type = pointer_ast_type.AddConstModifier(); |
775 | |
776 | if (pointer_type->isVolatileType()) |
777 | pointer_ast_type = pointer_ast_type.AddVolatileModifier(); |
778 | |
779 | if (pointer_type->isRestrictedType()) |
780 | pointer_ast_type = pointer_ast_type.AddRestrictModifier(); |
781 | |
782 | return m_ast.GetSymbolFile()->MakeType( |
783 | uid: pointer_type->getSymIndexId(), name: ConstString(), byte_size: pointer_type->getLength(), |
784 | context: nullptr, LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
785 | compiler_qual_type: pointer_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
786 | } break; |
787 | default: |
788 | break; |
789 | } |
790 | return nullptr; |
791 | } |
792 | |
793 | bool PDBASTParser::CompleteTypeFromPDB( |
794 | lldb_private::CompilerType &compiler_type) { |
795 | if (GetClangASTImporter().CanImport(type: compiler_type)) |
796 | return GetClangASTImporter().CompleteType(compiler_type); |
797 | |
798 | // Remove the type from the forward declarations to avoid |
799 | // an endless recursion for types like a linked list. |
800 | clang::CXXRecordDecl *record_decl = |
801 | m_ast.GetAsCXXRecordDecl(type: compiler_type.GetOpaqueQualType()); |
802 | auto uid_it = m_forward_decl_to_uid.find(Val: record_decl); |
803 | if (uid_it == m_forward_decl_to_uid.end()) |
804 | return true; |
805 | |
806 | auto symbol_file = static_cast<SymbolFilePDB *>( |
807 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
808 | if (!symbol_file) |
809 | return false; |
810 | |
811 | std::unique_ptr<PDBSymbol> symbol = |
812 | symbol_file->GetPDBSession().getSymbolById(SymbolId: uid_it->getSecond()); |
813 | if (!symbol) |
814 | return false; |
815 | |
816 | m_forward_decl_to_uid.erase(I: uid_it); |
817 | |
818 | TypeSystemClang::SetHasExternalStorage(type: compiler_type.GetOpaqueQualType(), |
819 | has_extern: false); |
820 | |
821 | switch (symbol->getSymTag()) { |
822 | case PDB_SymType::UDT: { |
823 | auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(Val: symbol.get()); |
824 | if (!udt) |
825 | return false; |
826 | |
827 | return CompleteTypeFromUDT(symbol_file&: *symbol_file, compiler_type, udt&: *udt); |
828 | } |
829 | default: |
830 | llvm_unreachable("not a forward clang type decl!" ); |
831 | } |
832 | } |
833 | |
834 | clang::Decl * |
835 | PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { |
836 | uint32_t sym_id = symbol.getSymIndexId(); |
837 | auto it = m_uid_to_decl.find(Val: sym_id); |
838 | if (it != m_uid_to_decl.end()) |
839 | return it->second; |
840 | |
841 | auto symbol_file = static_cast<SymbolFilePDB *>( |
842 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
843 | if (!symbol_file) |
844 | return nullptr; |
845 | |
846 | // First of all, check if the symbol is a member of a class. Resolve the full |
847 | // class type and return the declaration from the cache if so. |
848 | auto tag = symbol.getSymTag(); |
849 | if (tag == PDB_SymType::Data || tag == PDB_SymType::Function) { |
850 | const IPDBSession &session = symbol.getSession(); |
851 | const IPDBRawSymbol &raw = symbol.getRawSymbol(); |
852 | |
853 | auto class_parent_id = raw.getClassParentId(); |
854 | if (std::unique_ptr<PDBSymbol> class_parent = |
855 | session.getSymbolById(SymbolId: class_parent_id)) { |
856 | auto class_parent_type = symbol_file->ResolveTypeUID(type_uid: class_parent_id); |
857 | if (!class_parent_type) |
858 | return nullptr; |
859 | |
860 | CompilerType class_parent_ct = class_parent_type->GetFullCompilerType(); |
861 | |
862 | // Look a declaration up in the cache after completing the class |
863 | clang::Decl *decl = m_uid_to_decl.lookup(Val: sym_id); |
864 | if (decl) |
865 | return decl; |
866 | |
867 | // A declaration was not found in the cache. It means that the symbol |
868 | // has the class parent, but the class doesn't have the symbol in its |
869 | // children list. |
870 | if (auto func = llvm::dyn_cast_or_null<PDBSymbolFunc>(Val: &symbol)) { |
871 | // Try to find a class child method with the same RVA and use its |
872 | // declaration if found. |
873 | if (uint32_t rva = func->getRelativeVirtualAddress()) { |
874 | if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolFunc>> |
875 | methods_enum = |
876 | class_parent->findAllChildren<PDBSymbolFunc>()) { |
877 | while (std::unique_ptr<PDBSymbolFunc> method = |
878 | methods_enum->getNext()) { |
879 | if (method->getRelativeVirtualAddress() == rva) { |
880 | decl = m_uid_to_decl.lookup(Val: method->getSymIndexId()); |
881 | if (decl) |
882 | break; |
883 | } |
884 | } |
885 | } |
886 | } |
887 | |
888 | // If no class methods with the same RVA were found, then create a new |
889 | // method. It is possible for template methods. |
890 | if (!decl) |
891 | decl = AddRecordMethod(symbol_file&: *symbol_file, record_type&: class_parent_ct, method: *func); |
892 | } |
893 | |
894 | if (decl) |
895 | m_uid_to_decl[sym_id] = decl; |
896 | |
897 | return decl; |
898 | } |
899 | } |
900 | |
901 | // If we are here, then the symbol is not belonging to a class and is not |
902 | // contained in the cache. So create a declaration for it. |
903 | switch (symbol.getSymTag()) { |
904 | case PDB_SymType::Data: { |
905 | auto data = llvm::dyn_cast<PDBSymbolData>(Val: &symbol); |
906 | assert(data); |
907 | |
908 | auto decl_context = GetDeclContextContainingSymbol(symbol); |
909 | assert(decl_context); |
910 | |
911 | // May be the current context is a class really, but we haven't found |
912 | // any class parent. This happens e.g. in the case of class static |
913 | // variables - they has two symbols, one is a child of the class when |
914 | // another is a child of the exe. So always complete the parent and use |
915 | // an existing declaration if possible. |
916 | if (auto parent_decl = llvm::dyn_cast_or_null<clang::TagDecl>(Val: decl_context)) |
917 | m_ast.GetCompleteDecl(parent_decl); |
918 | |
919 | std::string name = |
920 | std::string(MSVCUndecoratedNameParser::DropScope(name: data->getName())); |
921 | |
922 | // Check if the current context already contains the symbol with the name. |
923 | clang::Decl *decl = |
924 | GetDeclFromContextByName(ast: m_ast.getASTContext(), decl_context: *decl_context, name); |
925 | if (!decl) { |
926 | auto type = symbol_file->ResolveTypeUID(type_uid: data->getTypeId()); |
927 | if (!type) |
928 | return nullptr; |
929 | |
930 | decl = m_ast.CreateVariableDeclaration( |
931 | decl_context, owning_module: OptionalClangModuleID(), name: name.c_str(), |
932 | type: ClangUtil::GetQualType(ct: type->GetLayoutCompilerType())); |
933 | } |
934 | |
935 | m_uid_to_decl[sym_id] = decl; |
936 | |
937 | return decl; |
938 | } |
939 | case PDB_SymType::Function: { |
940 | auto func = llvm::dyn_cast<PDBSymbolFunc>(Val: &symbol); |
941 | assert(func); |
942 | |
943 | auto decl_context = GetDeclContextContainingSymbol(symbol); |
944 | assert(decl_context); |
945 | |
946 | std::string name = |
947 | std::string(MSVCUndecoratedNameParser::DropScope(name: func->getName())); |
948 | |
949 | Type *type = symbol_file->ResolveTypeUID(type_uid: sym_id); |
950 | if (!type) |
951 | return nullptr; |
952 | |
953 | auto storage = func->isStatic() ? clang::StorageClass::SC_Static |
954 | : clang::StorageClass::SC_None; |
955 | |
956 | auto decl = m_ast.CreateFunctionDeclaration( |
957 | decl_ctx: decl_context, owning_module: OptionalClangModuleID(), name, |
958 | function_Type: type->GetForwardCompilerType(), storage, is_inline: func->hasInlineAttribute()); |
959 | |
960 | std::vector<clang::ParmVarDecl *> params; |
961 | if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) { |
962 | if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg>> |
963 | arg_enum = sig->findAllChildren<PDBSymbolTypeFunctionArg>()) { |
964 | while (std::unique_ptr<PDBSymbolTypeFunctionArg> arg = |
965 | arg_enum->getNext()) { |
966 | Type *arg_type = symbol_file->ResolveTypeUID(type_uid: arg->getTypeId()); |
967 | if (!arg_type) |
968 | continue; |
969 | |
970 | clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration( |
971 | decl, OptionalClangModuleID(), nullptr, |
972 | arg_type->GetForwardCompilerType(), clang::SC_None, true); |
973 | if (param) |
974 | params.push_back(x: param); |
975 | } |
976 | } |
977 | } |
978 | if (params.size()) |
979 | m_ast.SetFunctionParameters(function_decl: decl, params); |
980 | |
981 | m_uid_to_decl[sym_id] = decl; |
982 | |
983 | return decl; |
984 | } |
985 | default: { |
986 | // It's not a variable and not a function, check if it's a type |
987 | Type *type = symbol_file->ResolveTypeUID(type_uid: sym_id); |
988 | if (!type) |
989 | return nullptr; |
990 | |
991 | return m_uid_to_decl.lookup(Val: sym_id); |
992 | } |
993 | } |
994 | } |
995 | |
996 | clang::DeclContext * |
997 | PDBASTParser::GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol) { |
998 | if (symbol.getSymTag() == PDB_SymType::Function) { |
999 | clang::DeclContext *result = |
1000 | llvm::dyn_cast_or_null<clang::FunctionDecl>(Val: GetDeclForSymbol(symbol)); |
1001 | |
1002 | if (result) |
1003 | m_decl_context_to_uid[result] = symbol.getSymIndexId(); |
1004 | |
1005 | return result; |
1006 | } |
1007 | |
1008 | auto symbol_file = static_cast<SymbolFilePDB *>( |
1009 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
1010 | if (!symbol_file) |
1011 | return nullptr; |
1012 | |
1013 | auto type = symbol_file->ResolveTypeUID(type_uid: symbol.getSymIndexId()); |
1014 | if (!type) |
1015 | return nullptr; |
1016 | |
1017 | clang::DeclContext *result = |
1018 | m_ast.GetDeclContextForType(type: type->GetForwardCompilerType()); |
1019 | |
1020 | if (result) |
1021 | m_decl_context_to_uid[result] = symbol.getSymIndexId(); |
1022 | |
1023 | return result; |
1024 | } |
1025 | |
1026 | clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol( |
1027 | const llvm::pdb::PDBSymbol &symbol) { |
1028 | auto parent = GetClassOrFunctionParent(symbol); |
1029 | while (parent) { |
1030 | if (auto parent_context = GetDeclContextForSymbol(symbol: *parent)) |
1031 | return parent_context; |
1032 | |
1033 | parent = GetClassOrFunctionParent(symbol: *parent); |
1034 | } |
1035 | |
1036 | // We can't find any class or function parent of the symbol. So analyze |
1037 | // the full symbol name. The symbol may be belonging to a namespace |
1038 | // or function (or even to a class if it's e.g. a static variable symbol). |
1039 | |
1040 | // TODO: Make clang to emit full names for variables in namespaces |
1041 | // (as MSVC does) |
1042 | |
1043 | std::string name(symbol.getRawSymbol().getName()); |
1044 | MSVCUndecoratedNameParser parser(name); |
1045 | llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); |
1046 | if (specs.empty()) |
1047 | return m_ast.GetTranslationUnitDecl(); |
1048 | |
1049 | auto symbol_file = static_cast<SymbolFilePDB *>( |
1050 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
1051 | if (!symbol_file) |
1052 | return m_ast.GetTranslationUnitDecl(); |
1053 | |
1054 | auto global = symbol_file->GetPDBSession().getGlobalScope(); |
1055 | if (!global) |
1056 | return m_ast.GetTranslationUnitDecl(); |
1057 | |
1058 | bool has_type_or_function_parent = false; |
1059 | clang::DeclContext *curr_context = m_ast.GetTranslationUnitDecl(); |
1060 | for (std::size_t i = 0; i < specs.size() - 1; i++) { |
1061 | // Check if there is a function or a type with the current context's name. |
1062 | if (std::unique_ptr<IPDBEnumSymbols> children_enum = global->findChildren( |
1063 | Type: PDB_SymType::None, Name: specs[i].GetFullName(), Flags: NS_CaseSensitive)) { |
1064 | while (IPDBEnumChildren<PDBSymbol>::ChildTypePtr child = |
1065 | children_enum->getNext()) { |
1066 | if (clang::DeclContext *child_context = |
1067 | GetDeclContextForSymbol(symbol: *child)) { |
1068 | // Note that `GetDeclContextForSymbol' retrieves |
1069 | // a declaration context for functions and types only, |
1070 | // so if we are here then `child_context' is guaranteed |
1071 | // a function or a type declaration context. |
1072 | has_type_or_function_parent = true; |
1073 | curr_context = child_context; |
1074 | } |
1075 | } |
1076 | } |
1077 | |
1078 | // If there were no functions or types above then retrieve a namespace with |
1079 | // the current context's name. There can be no namespaces inside a function |
1080 | // or a type. We check it to avoid fake namespaces such as `__l2': |
1081 | // `N0::N1::CClass::PrivateFunc::__l2::InnerFuncStruct' |
1082 | if (!has_type_or_function_parent) { |
1083 | std::string namespace_name = std::string(specs[i].GetBaseName()); |
1084 | const char *namespace_name_c_str = |
1085 | IsAnonymousNamespaceName(name: namespace_name) ? nullptr |
1086 | : namespace_name.data(); |
1087 | clang::NamespaceDecl *namespace_decl = |
1088 | m_ast.GetUniqueNamespaceDeclaration( |
1089 | name: namespace_name_c_str, decl_ctx: curr_context, owning_module: OptionalClangModuleID()); |
1090 | |
1091 | m_parent_to_namespaces[curr_context].insert(x: namespace_decl); |
1092 | m_namespaces.insert(x: namespace_decl); |
1093 | |
1094 | curr_context = namespace_decl; |
1095 | } |
1096 | } |
1097 | |
1098 | return curr_context; |
1099 | } |
1100 | |
1101 | void PDBASTParser::ParseDeclsForDeclContext( |
1102 | const clang::DeclContext *decl_context) { |
1103 | auto symbol_file = static_cast<SymbolFilePDB *>( |
1104 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
1105 | if (!symbol_file) |
1106 | return; |
1107 | |
1108 | IPDBSession &session = symbol_file->GetPDBSession(); |
1109 | auto symbol_up = |
1110 | session.getSymbolById(SymbolId: m_decl_context_to_uid.lookup(Val: decl_context)); |
1111 | auto global_up = session.getGlobalScope(); |
1112 | |
1113 | PDBSymbol *symbol; |
1114 | if (symbol_up) |
1115 | symbol = symbol_up.get(); |
1116 | else if (global_up) |
1117 | symbol = global_up.get(); |
1118 | else |
1119 | return; |
1120 | |
1121 | if (auto children = symbol->findAllChildren()) |
1122 | while (auto child = children->getNext()) |
1123 | GetDeclForSymbol(symbol: *child); |
1124 | } |
1125 | |
1126 | clang::NamespaceDecl * |
1127 | PDBASTParser::FindNamespaceDecl(const clang::DeclContext *parent, |
1128 | llvm::StringRef name) { |
1129 | NamespacesSet *set; |
1130 | if (parent) { |
1131 | auto pit = m_parent_to_namespaces.find(Val: parent); |
1132 | if (pit == m_parent_to_namespaces.end()) |
1133 | return nullptr; |
1134 | |
1135 | set = &pit->second; |
1136 | } else { |
1137 | set = &m_namespaces; |
1138 | } |
1139 | assert(set); |
1140 | |
1141 | for (clang::NamespaceDecl *namespace_decl : *set) |
1142 | if (namespace_decl->getName().equals(name)) |
1143 | return namespace_decl; |
1144 | |
1145 | for (clang::NamespaceDecl *namespace_decl : *set) |
1146 | if (namespace_decl->isAnonymousNamespace()) |
1147 | return FindNamespaceDecl(namespace_decl, name); |
1148 | |
1149 | return nullptr; |
1150 | } |
1151 | |
1152 | bool PDBASTParser::AddEnumValue(CompilerType enum_type, |
1153 | const PDBSymbolData &enum_value) { |
1154 | Declaration decl; |
1155 | Variant v = enum_value.getValue(); |
1156 | std::string name = |
1157 | std::string(MSVCUndecoratedNameParser::DropScope(name: enum_value.getName())); |
1158 | int64_t raw_value; |
1159 | switch (v.Type) { |
1160 | case PDB_VariantType::Int8: |
1161 | raw_value = v.Value.Int8; |
1162 | break; |
1163 | case PDB_VariantType::Int16: |
1164 | raw_value = v.Value.Int16; |
1165 | break; |
1166 | case PDB_VariantType::Int32: |
1167 | raw_value = v.Value.Int32; |
1168 | break; |
1169 | case PDB_VariantType::Int64: |
1170 | raw_value = v.Value.Int64; |
1171 | break; |
1172 | case PDB_VariantType::UInt8: |
1173 | raw_value = v.Value.UInt8; |
1174 | break; |
1175 | case PDB_VariantType::UInt16: |
1176 | raw_value = v.Value.UInt16; |
1177 | break; |
1178 | case PDB_VariantType::UInt32: |
1179 | raw_value = v.Value.UInt32; |
1180 | break; |
1181 | case PDB_VariantType::UInt64: |
1182 | raw_value = v.Value.UInt64; |
1183 | break; |
1184 | default: |
1185 | return false; |
1186 | } |
1187 | CompilerType underlying_type = m_ast.GetEnumerationIntegerType(type: enum_type); |
1188 | uint32_t byte_size = m_ast.getASTContext().getTypeSize( |
1189 | T: ClangUtil::GetQualType(ct: underlying_type)); |
1190 | auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType( |
1191 | enum_type, decl, name: name.c_str(), enum_value: raw_value, enum_value_bit_size: byte_size * 8); |
1192 | if (!enum_constant_decl) |
1193 | return false; |
1194 | |
1195 | m_uid_to_decl[enum_value.getSymIndexId()] = enum_constant_decl; |
1196 | |
1197 | return true; |
1198 | } |
1199 | |
1200 | bool PDBASTParser::CompleteTypeFromUDT( |
1201 | lldb_private::SymbolFile &symbol_file, |
1202 | lldb_private::CompilerType &compiler_type, |
1203 | llvm::pdb::PDBSymbolTypeUDT &udt) { |
1204 | ClangASTImporter::LayoutInfo layout_info; |
1205 | layout_info.bit_size = udt.getLength() * 8; |
1206 | |
1207 | auto nested_enums = udt.findAllChildren<PDBSymbolTypeUDT>(); |
1208 | if (nested_enums) |
1209 | while (auto nested = nested_enums->getNext()) |
1210 | symbol_file.ResolveTypeUID(type_uid: nested->getSymIndexId()); |
1211 | |
1212 | auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>(); |
1213 | if (bases_enum) |
1214 | AddRecordBases(symbol_file, record_type&: compiler_type, |
1215 | record_kind: TranslateUdtKind(pdb_kind: udt.getUdtKind()), bases_enum&: *bases_enum, |
1216 | layout_info); |
1217 | |
1218 | auto members_enum = udt.findAllChildren<PDBSymbolData>(); |
1219 | if (members_enum) |
1220 | AddRecordMembers(symbol_file, record_type&: compiler_type, members_enum&: *members_enum, layout_info); |
1221 | |
1222 | auto methods_enum = udt.findAllChildren<PDBSymbolFunc>(); |
1223 | if (methods_enum) |
1224 | AddRecordMethods(symbol_file, record_type&: compiler_type, methods_enum&: *methods_enum); |
1225 | |
1226 | m_ast.AddMethodOverridesForCXXRecordType(type: compiler_type.GetOpaqueQualType()); |
1227 | TypeSystemClang::BuildIndirectFields(type: compiler_type); |
1228 | TypeSystemClang::CompleteTagDeclarationDefinition(type: compiler_type); |
1229 | |
1230 | clang::CXXRecordDecl *record_decl = |
1231 | m_ast.GetAsCXXRecordDecl(type: compiler_type.GetOpaqueQualType()); |
1232 | if (!record_decl) |
1233 | return static_cast<bool>(compiler_type); |
1234 | |
1235 | GetClangASTImporter().SetRecordLayout(record_decl, layout_info); |
1236 | |
1237 | return static_cast<bool>(compiler_type); |
1238 | } |
1239 | |
1240 | void PDBASTParser::AddRecordMembers( |
1241 | lldb_private::SymbolFile &symbol_file, |
1242 | lldb_private::CompilerType &record_type, |
1243 | PDBDataSymbolEnumerator &members_enum, |
1244 | lldb_private::ClangASTImporter::LayoutInfo &layout_info) { |
1245 | while (auto member = members_enum.getNext()) { |
1246 | if (member->isCompilerGenerated()) |
1247 | continue; |
1248 | |
1249 | auto member_name = member->getName(); |
1250 | |
1251 | auto member_type = symbol_file.ResolveTypeUID(type_uid: member->getTypeId()); |
1252 | if (!member_type) |
1253 | continue; |
1254 | |
1255 | auto member_comp_type = member_type->GetLayoutCompilerType(); |
1256 | if (!member_comp_type.GetCompleteType()) { |
1257 | symbol_file.GetObjectFile()->GetModule()->ReportError( |
1258 | format: ":: Class '{0}' has a member '{1}' of type '{2}' " |
1259 | "which does not have a complete definition." , |
1260 | args: record_type.GetTypeName().GetCString(), args: member_name.c_str(), |
1261 | args: member_comp_type.GetTypeName().GetCString()); |
1262 | if (TypeSystemClang::StartTagDeclarationDefinition(type: member_comp_type)) |
1263 | TypeSystemClang::CompleteTagDeclarationDefinition(type: member_comp_type); |
1264 | } |
1265 | |
1266 | auto access = TranslateMemberAccess(access: member->getAccess()); |
1267 | |
1268 | switch (member->getDataKind()) { |
1269 | case PDB_DataKind::Member: { |
1270 | auto location_type = member->getLocationType(); |
1271 | |
1272 | auto bit_size = member->getLength(); |
1273 | if (location_type == PDB_LocType::ThisRel) |
1274 | bit_size *= 8; |
1275 | |
1276 | auto decl = TypeSystemClang::AddFieldToRecordType( |
1277 | type: record_type, name: member_name.c_str(), field_type: member_comp_type, access, bitfield_bit_size: bit_size); |
1278 | if (!decl) |
1279 | continue; |
1280 | |
1281 | m_uid_to_decl[member->getSymIndexId()] = decl; |
1282 | |
1283 | auto offset = member->getOffset() * 8; |
1284 | if (location_type == PDB_LocType::BitField) |
1285 | offset += member->getBitPosition(); |
1286 | |
1287 | layout_info.field_offsets.insert(KV: std::make_pair(x&: decl, y&: offset)); |
1288 | |
1289 | break; |
1290 | } |
1291 | case PDB_DataKind::StaticMember: { |
1292 | auto decl = TypeSystemClang::AddVariableToRecordType( |
1293 | type: record_type, name: member_name.c_str(), var_type: member_comp_type, access); |
1294 | if (!decl) |
1295 | continue; |
1296 | |
1297 | // Static constant members may be a const[expr] declaration. |
1298 | // Query the symbol's value as the variable initializer if valid. |
1299 | if (member_comp_type.IsConst()) { |
1300 | auto value = member->getValue(); |
1301 | if (value.Type == llvm::pdb::Empty) { |
1302 | LLDB_LOG(GetLog(LLDBLog::AST), |
1303 | "Class '{0}' has member '{1}' of type '{2}' with an unknown " |
1304 | "constant size." , |
1305 | record_type.GetTypeName(), member_name, |
1306 | member_comp_type.GetTypeName()); |
1307 | continue; |
1308 | } |
1309 | |
1310 | clang::QualType qual_type = decl->getType(); |
1311 | unsigned type_width = m_ast.getASTContext().getIntWidth(T: qual_type); |
1312 | unsigned constant_width = value.getBitWidth(); |
1313 | |
1314 | if (qual_type->isIntegralOrEnumerationType()) { |
1315 | if (type_width >= constant_width) { |
1316 | TypeSystemClang::SetIntegerInitializerForVariable( |
1317 | var: decl, init_value: value.toAPSInt().extOrTrunc(width: type_width)); |
1318 | } else { |
1319 | LLDB_LOG(GetLog(LLDBLog::AST), |
1320 | "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) " |
1321 | "which resolves to a wider constant value ({4} bits). " |
1322 | "Ignoring constant." , |
1323 | record_type.GetTypeName(), member_name, |
1324 | member_comp_type.GetTypeName(), type_width, |
1325 | constant_width); |
1326 | } |
1327 | } else { |
1328 | switch (member_comp_type.GetBasicTypeEnumeration()) { |
1329 | case lldb::eBasicTypeFloat: |
1330 | case lldb::eBasicTypeDouble: |
1331 | case lldb::eBasicTypeLongDouble: |
1332 | if (type_width == constant_width) { |
1333 | TypeSystemClang::SetFloatingInitializerForVariable( |
1334 | var: decl, init_value: value.toAPFloat()); |
1335 | decl->setConstexpr(true); |
1336 | } else { |
1337 | LLDB_LOG(GetLog(LLDBLog::AST), |
1338 | "Class '{0}' has a member '{1}' of type '{2}' ({3} " |
1339 | "bits) which resolves to a constant value of mismatched " |
1340 | "width ({4} bits). Ignoring constant." , |
1341 | record_type.GetTypeName(), member_name, |
1342 | member_comp_type.GetTypeName(), type_width, |
1343 | constant_width); |
1344 | } |
1345 | break; |
1346 | default: |
1347 | break; |
1348 | } |
1349 | } |
1350 | } |
1351 | |
1352 | m_uid_to_decl[member->getSymIndexId()] = decl; |
1353 | |
1354 | break; |
1355 | } |
1356 | default: |
1357 | llvm_unreachable("unsupported PDB data kind" ); |
1358 | } |
1359 | } |
1360 | } |
1361 | |
1362 | void PDBASTParser::AddRecordBases( |
1363 | lldb_private::SymbolFile &symbol_file, |
1364 | lldb_private::CompilerType &record_type, int record_kind, |
1365 | PDBBaseClassSymbolEnumerator &bases_enum, |
1366 | lldb_private::ClangASTImporter::LayoutInfo &layout_info) const { |
1367 | std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> base_classes; |
1368 | |
1369 | while (auto base = bases_enum.getNext()) { |
1370 | auto base_type = symbol_file.ResolveTypeUID(type_uid: base->getTypeId()); |
1371 | if (!base_type) |
1372 | continue; |
1373 | |
1374 | auto base_comp_type = base_type->GetFullCompilerType(); |
1375 | if (!base_comp_type.GetCompleteType()) { |
1376 | symbol_file.GetObjectFile()->GetModule()->ReportError( |
1377 | format: ":: Class '{0}' has a base class '{1}' " |
1378 | "which does not have a complete definition." , |
1379 | args: record_type.GetTypeName().GetCString(), |
1380 | args: base_comp_type.GetTypeName().GetCString()); |
1381 | if (TypeSystemClang::StartTagDeclarationDefinition(type: base_comp_type)) |
1382 | TypeSystemClang::CompleteTagDeclarationDefinition(type: base_comp_type); |
1383 | } |
1384 | |
1385 | auto access = TranslateMemberAccess(access: base->getAccess()); |
1386 | |
1387 | auto is_virtual = base->isVirtualBaseClass(); |
1388 | |
1389 | std::unique_ptr<clang::CXXBaseSpecifier> base_spec = |
1390 | m_ast.CreateBaseClassSpecifier( |
1391 | type: base_comp_type.GetOpaqueQualType(), access, is_virtual, |
1392 | base_of_class: record_kind == llvm::to_underlying(E: clang::TagTypeKind::Class)); |
1393 | lldbassert(base_spec); |
1394 | |
1395 | base_classes.push_back(x: std::move(base_spec)); |
1396 | |
1397 | if (is_virtual) |
1398 | continue; |
1399 | |
1400 | auto decl = m_ast.GetAsCXXRecordDecl(type: base_comp_type.GetOpaqueQualType()); |
1401 | if (!decl) |
1402 | continue; |
1403 | |
1404 | auto offset = clang::CharUnits::fromQuantity(Quantity: base->getOffset()); |
1405 | layout_info.base_offsets.insert(KV: std::make_pair(x&: decl, y&: offset)); |
1406 | } |
1407 | |
1408 | m_ast.TransferBaseClasses(type: record_type.GetOpaqueQualType(), |
1409 | bases: std::move(base_classes)); |
1410 | } |
1411 | |
1412 | void PDBASTParser::AddRecordMethods(lldb_private::SymbolFile &symbol_file, |
1413 | lldb_private::CompilerType &record_type, |
1414 | PDBFuncSymbolEnumerator &methods_enum) { |
1415 | while (std::unique_ptr<PDBSymbolFunc> method = methods_enum.getNext()) |
1416 | if (clang::CXXMethodDecl *decl = |
1417 | AddRecordMethod(symbol_file, record_type, method: *method)) |
1418 | m_uid_to_decl[method->getSymIndexId()] = decl; |
1419 | } |
1420 | |
1421 | clang::CXXMethodDecl * |
1422 | PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, |
1423 | lldb_private::CompilerType &record_type, |
1424 | const llvm::pdb::PDBSymbolFunc &method) const { |
1425 | std::string name = |
1426 | std::string(MSVCUndecoratedNameParser::DropScope(name: method.getName())); |
1427 | |
1428 | Type *method_type = symbol_file.ResolveTypeUID(type_uid: method.getSymIndexId()); |
1429 | // MSVC specific __vecDelDtor. |
1430 | if (!method_type) |
1431 | return nullptr; |
1432 | |
1433 | CompilerType method_comp_type = method_type->GetFullCompilerType(); |
1434 | if (!method_comp_type.GetCompleteType()) { |
1435 | symbol_file.GetObjectFile()->GetModule()->ReportError( |
1436 | format: ":: Class '{0}' has a method '{1}' whose type cannot be completed." , |
1437 | args: record_type.GetTypeName().GetCString(), |
1438 | args: method_comp_type.GetTypeName().GetCString()); |
1439 | if (TypeSystemClang::StartTagDeclarationDefinition(type: method_comp_type)) |
1440 | TypeSystemClang::CompleteTagDeclarationDefinition(type: method_comp_type); |
1441 | } |
1442 | |
1443 | AccessType access = TranslateMemberAccess(access: method.getAccess()); |
1444 | if (access == eAccessNone) |
1445 | access = eAccessPublic; |
1446 | |
1447 | // TODO: get mangled name for the method. |
1448 | return m_ast.AddMethodToCXXRecordType( |
1449 | type: record_type.GetOpaqueQualType(), name: name.c_str(), |
1450 | /*mangled_name*/ nullptr, method_type: method_comp_type, access, is_virtual: method.isVirtual(), |
1451 | is_static: method.isStatic(), is_inline: method.hasInlineAttribute(), |
1452 | /*is_explicit*/ false, // FIXME: Need this field in CodeView. |
1453 | /*is_attr_used*/ false, |
1454 | /*is_artificial*/ method.isCompilerGenerated()); |
1455 | } |
1456 | |