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); |
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_context, |
509 | OptionalClangModuleID(), decl, |
510 | builtin_type, 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 = m_ast.CreateFunctionType( |
657 | result_type: return_ast_type, args: arg_list, is_variadic, type_quals, cc); |
658 | |
659 | AddSourceInfoToDecl(symbol: type, decl); |
660 | return m_ast.GetSymbolFile()->MakeType( |
661 | uid: type.getSymIndexId(), name: ConstString(name), byte_size: std::nullopt, context: nullptr, |
662 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
663 | compiler_qual_type: func_sig_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
664 | } break; |
665 | case PDB_SymType::ArrayType: { |
666 | auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(Val: &type); |
667 | assert(array_type); |
668 | uint32_t num_elements = array_type->getCount(); |
669 | uint32_t element_uid = array_type->getElementTypeId(); |
670 | std::optional<uint64_t> bytes; |
671 | if (uint64_t size = array_type->getLength()) |
672 | bytes = size; |
673 | |
674 | SymbolFile *symbol_file = m_ast.GetSymbolFile(); |
675 | if (!symbol_file) |
676 | return nullptr; |
677 | |
678 | // If array rank > 0, PDB gives the element type at N=0. So element type |
679 | // will parsed in the order N=0, N=1,..., N=rank sequentially. |
680 | lldb_private::Type *element_type = symbol_file->ResolveTypeUID(type_uid: element_uid); |
681 | if (!element_type) |
682 | return nullptr; |
683 | |
684 | CompilerType element_ast_type = element_type->GetForwardCompilerType(); |
685 | // If element type is UDT, it needs to be complete. |
686 | if (TypeSystemClang::IsCXXClassType(type: element_ast_type) && |
687 | !element_ast_type.GetCompleteType()) { |
688 | if (TypeSystemClang::StartTagDeclarationDefinition(type: element_ast_type)) { |
689 | TypeSystemClang::CompleteTagDeclarationDefinition(type: element_ast_type); |
690 | } else { |
691 | // We are not able to start definition. |
692 | return nullptr; |
693 | } |
694 | } |
695 | CompilerType array_ast_type = m_ast.CreateArrayType( |
696 | element_type: element_ast_type, element_count: num_elements, /*is_gnu_vector*/ is_vector: false); |
697 | TypeSP type_sp = m_ast.GetSymbolFile()->MakeType( |
698 | uid: array_type->getSymIndexId(), name: ConstString(), byte_size: bytes, context: nullptr, |
699 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
700 | compiler_qual_type: array_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
701 | type_sp->SetEncodingType(element_type); |
702 | return type_sp; |
703 | } break; |
704 | case PDB_SymType::BuiltinType: { |
705 | auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(Val: &type); |
706 | assert(builtin_type); |
707 | PDB_BuiltinType builtin_kind = builtin_type->getBuiltinType(); |
708 | if (builtin_kind == PDB_BuiltinType::None) |
709 | return nullptr; |
710 | |
711 | std::optional<uint64_t> bytes; |
712 | if (uint64_t size = builtin_type->getLength()) |
713 | bytes = size; |
714 | Encoding encoding = TranslateBuiltinEncoding(type: builtin_kind); |
715 | CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize( |
716 | clang_ast&: m_ast, pdb_type: *builtin_type, encoding, width: bytes.value_or(u: 0) * 8); |
717 | |
718 | if (builtin_type->isConstType()) |
719 | builtin_ast_type = builtin_ast_type.AddConstModifier(); |
720 | |
721 | if (builtin_type->isVolatileType()) |
722 | builtin_ast_type = builtin_ast_type.AddVolatileModifier(); |
723 | |
724 | auto type_name = GetPDBBuiltinTypeName(pdb_type: *builtin_type, compiler_type&: builtin_ast_type); |
725 | |
726 | return m_ast.GetSymbolFile()->MakeType( |
727 | uid: builtin_type->getSymIndexId(), name: type_name, byte_size: bytes, context: nullptr, |
728 | LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
729 | compiler_qual_type: builtin_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
730 | } break; |
731 | case PDB_SymType::PointerType: { |
732 | auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(Val: &type); |
733 | assert(pointer_type); |
734 | |
735 | SymbolFile *symbol_file = m_ast.GetSymbolFile(); |
736 | if (!symbol_file) |
737 | return nullptr; |
738 | |
739 | Type *pointee_type = symbol_file->ResolveTypeUID( |
740 | type_uid: pointer_type->getPointeeType()->getSymIndexId()); |
741 | if (!pointee_type) |
742 | return nullptr; |
743 | |
744 | if (pointer_type->isPointerToDataMember() || |
745 | pointer_type->isPointerToMemberFunction()) { |
746 | auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId(); |
747 | auto class_parent_type = symbol_file->ResolveTypeUID(type_uid: class_parent_uid); |
748 | assert(class_parent_type); |
749 | |
750 | CompilerType pointer_ast_type; |
751 | pointer_ast_type = TypeSystemClang::CreateMemberPointerType( |
752 | type: class_parent_type->GetLayoutCompilerType(), |
753 | pointee_type: pointee_type->GetForwardCompilerType()); |
754 | assert(pointer_ast_type); |
755 | |
756 | return m_ast.GetSymbolFile()->MakeType( |
757 | uid: pointer_type->getSymIndexId(), name: ConstString(), |
758 | byte_size: pointer_type->getLength(), context: nullptr, LLDB_INVALID_UID, |
759 | encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, compiler_qual_type: pointer_ast_type, |
760 | compiler_type_resolve_state: lldb_private::Type::ResolveState::Forward); |
761 | } |
762 | |
763 | CompilerType pointer_ast_type; |
764 | pointer_ast_type = pointee_type->GetFullCompilerType(); |
765 | if (pointer_type->isReference()) |
766 | pointer_ast_type = pointer_ast_type.GetLValueReferenceType(); |
767 | else if (pointer_type->isRValueReference()) |
768 | pointer_ast_type = pointer_ast_type.GetRValueReferenceType(); |
769 | else |
770 | pointer_ast_type = pointer_ast_type.GetPointerType(); |
771 | |
772 | if (pointer_type->isConstType()) |
773 | pointer_ast_type = pointer_ast_type.AddConstModifier(); |
774 | |
775 | if (pointer_type->isVolatileType()) |
776 | pointer_ast_type = pointer_ast_type.AddVolatileModifier(); |
777 | |
778 | if (pointer_type->isRestrictedType()) |
779 | pointer_ast_type = pointer_ast_type.AddRestrictModifier(); |
780 | |
781 | return m_ast.GetSymbolFile()->MakeType( |
782 | uid: pointer_type->getSymIndexId(), name: ConstString(), byte_size: pointer_type->getLength(), |
783 | context: nullptr, LLDB_INVALID_UID, encoding_uid_type: lldb_private::Type::eEncodingIsUID, decl, |
784 | compiler_qual_type: pointer_ast_type, compiler_type_resolve_state: lldb_private::Type::ResolveState::Full); |
785 | } break; |
786 | default: |
787 | break; |
788 | } |
789 | return nullptr; |
790 | } |
791 | |
792 | bool PDBASTParser::CompleteTypeFromPDB( |
793 | lldb_private::CompilerType &compiler_type) { |
794 | if (GetClangASTImporter().CanImport(type: compiler_type)) |
795 | return GetClangASTImporter().CompleteType(compiler_type); |
796 | |
797 | // Remove the type from the forward declarations to avoid |
798 | // an endless recursion for types like a linked list. |
799 | clang::CXXRecordDecl *record_decl = |
800 | m_ast.GetAsCXXRecordDecl(type: compiler_type.GetOpaqueQualType()); |
801 | auto uid_it = m_forward_decl_to_uid.find(Val: record_decl); |
802 | if (uid_it == m_forward_decl_to_uid.end()) |
803 | return true; |
804 | |
805 | auto symbol_file = static_cast<SymbolFilePDB *>( |
806 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
807 | if (!symbol_file) |
808 | return false; |
809 | |
810 | std::unique_ptr<PDBSymbol> symbol = |
811 | symbol_file->GetPDBSession().getSymbolById(SymbolId: uid_it->getSecond()); |
812 | if (!symbol) |
813 | return false; |
814 | |
815 | m_forward_decl_to_uid.erase(I: uid_it); |
816 | |
817 | TypeSystemClang::SetHasExternalStorage(type: compiler_type.GetOpaqueQualType(), |
818 | has_extern: false); |
819 | |
820 | switch (symbol->getSymTag()) { |
821 | case PDB_SymType::UDT: { |
822 | auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(Val: symbol.get()); |
823 | if (!udt) |
824 | return false; |
825 | |
826 | return CompleteTypeFromUDT(symbol_file&: *symbol_file, compiler_type, udt&: *udt); |
827 | } |
828 | default: |
829 | llvm_unreachable("not a forward clang type decl!" ); |
830 | } |
831 | } |
832 | |
833 | clang::Decl * |
834 | PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { |
835 | uint32_t sym_id = symbol.getSymIndexId(); |
836 | auto it = m_uid_to_decl.find(Val: sym_id); |
837 | if (it != m_uid_to_decl.end()) |
838 | return it->second; |
839 | |
840 | auto symbol_file = static_cast<SymbolFilePDB *>( |
841 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
842 | if (!symbol_file) |
843 | return nullptr; |
844 | |
845 | // First of all, check if the symbol is a member of a class. Resolve the full |
846 | // class type and return the declaration from the cache if so. |
847 | auto tag = symbol.getSymTag(); |
848 | if (tag == PDB_SymType::Data || tag == PDB_SymType::Function) { |
849 | const IPDBSession &session = symbol.getSession(); |
850 | const IPDBRawSymbol &raw = symbol.getRawSymbol(); |
851 | |
852 | auto class_parent_id = raw.getClassParentId(); |
853 | if (std::unique_ptr<PDBSymbol> class_parent = |
854 | session.getSymbolById(SymbolId: class_parent_id)) { |
855 | auto class_parent_type = symbol_file->ResolveTypeUID(type_uid: class_parent_id); |
856 | if (!class_parent_type) |
857 | return nullptr; |
858 | |
859 | CompilerType class_parent_ct = class_parent_type->GetFullCompilerType(); |
860 | |
861 | // Look a declaration up in the cache after completing the class |
862 | clang::Decl *decl = m_uid_to_decl.lookup(Val: sym_id); |
863 | if (decl) |
864 | return decl; |
865 | |
866 | // A declaration was not found in the cache. It means that the symbol |
867 | // has the class parent, but the class doesn't have the symbol in its |
868 | // children list. |
869 | if (auto func = llvm::dyn_cast_or_null<PDBSymbolFunc>(Val: &symbol)) { |
870 | // Try to find a class child method with the same RVA and use its |
871 | // declaration if found. |
872 | if (uint32_t rva = func->getRelativeVirtualAddress()) { |
873 | if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolFunc>> |
874 | methods_enum = |
875 | class_parent->findAllChildren<PDBSymbolFunc>()) { |
876 | while (std::unique_ptr<PDBSymbolFunc> method = |
877 | methods_enum->getNext()) { |
878 | if (method->getRelativeVirtualAddress() == rva) { |
879 | decl = m_uid_to_decl.lookup(Val: method->getSymIndexId()); |
880 | if (decl) |
881 | break; |
882 | } |
883 | } |
884 | } |
885 | } |
886 | |
887 | // If no class methods with the same RVA were found, then create a new |
888 | // method. It is possible for template methods. |
889 | if (!decl) |
890 | decl = AddRecordMethod(symbol_file&: *symbol_file, record_type&: class_parent_ct, method: *func); |
891 | } |
892 | |
893 | if (decl) |
894 | m_uid_to_decl[sym_id] = decl; |
895 | |
896 | return decl; |
897 | } |
898 | } |
899 | |
900 | // If we are here, then the symbol is not belonging to a class and is not |
901 | // contained in the cache. So create a declaration for it. |
902 | switch (symbol.getSymTag()) { |
903 | case PDB_SymType::Data: { |
904 | auto data = llvm::dyn_cast<PDBSymbolData>(Val: &symbol); |
905 | assert(data); |
906 | |
907 | auto decl_context = GetDeclContextContainingSymbol(symbol); |
908 | assert(decl_context); |
909 | |
910 | // May be the current context is a class really, but we haven't found |
911 | // any class parent. This happens e.g. in the case of class static |
912 | // variables - they has two symbols, one is a child of the class when |
913 | // another is a child of the exe. So always complete the parent and use |
914 | // an existing declaration if possible. |
915 | if (auto parent_decl = llvm::dyn_cast_or_null<clang::TagDecl>(Val: decl_context)) |
916 | m_ast.GetCompleteDecl(parent_decl); |
917 | |
918 | std::string name = |
919 | std::string(MSVCUndecoratedNameParser::DropScope(name: data->getName())); |
920 | |
921 | // Check if the current context already contains the symbol with the name. |
922 | clang::Decl *decl = |
923 | GetDeclFromContextByName(ast: m_ast.getASTContext(), decl_context: *decl_context, name); |
924 | if (!decl) { |
925 | auto type = symbol_file->ResolveTypeUID(type_uid: data->getTypeId()); |
926 | if (!type) |
927 | return nullptr; |
928 | |
929 | decl = m_ast.CreateVariableDeclaration( |
930 | decl_context, owning_module: OptionalClangModuleID(), name: name.c_str(), |
931 | type: ClangUtil::GetQualType(ct: type->GetLayoutCompilerType())); |
932 | } |
933 | |
934 | m_uid_to_decl[sym_id] = decl; |
935 | |
936 | return decl; |
937 | } |
938 | case PDB_SymType::Function: { |
939 | auto func = llvm::dyn_cast<PDBSymbolFunc>(Val: &symbol); |
940 | assert(func); |
941 | |
942 | auto decl_context = GetDeclContextContainingSymbol(symbol); |
943 | assert(decl_context); |
944 | |
945 | std::string name = |
946 | std::string(MSVCUndecoratedNameParser::DropScope(name: func->getName())); |
947 | |
948 | Type *type = symbol_file->ResolveTypeUID(type_uid: sym_id); |
949 | if (!type) |
950 | return nullptr; |
951 | |
952 | auto storage = func->isStatic() ? clang::StorageClass::SC_Static |
953 | : clang::StorageClass::SC_None; |
954 | |
955 | auto decl = m_ast.CreateFunctionDeclaration( |
956 | decl_ctx: decl_context, owning_module: OptionalClangModuleID(), name, |
957 | function_Type: type->GetForwardCompilerType(), storage, is_inline: func->hasInlineAttribute()); |
958 | |
959 | std::vector<clang::ParmVarDecl *> params; |
960 | if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) { |
961 | if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg>> |
962 | arg_enum = sig->findAllChildren<PDBSymbolTypeFunctionArg>()) { |
963 | while (std::unique_ptr<PDBSymbolTypeFunctionArg> arg = |
964 | arg_enum->getNext()) { |
965 | Type *arg_type = symbol_file->ResolveTypeUID(type_uid: arg->getTypeId()); |
966 | if (!arg_type) |
967 | continue; |
968 | |
969 | clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration( |
970 | decl, OptionalClangModuleID(), nullptr, |
971 | arg_type->GetForwardCompilerType(), clang::SC_None, true); |
972 | if (param) |
973 | params.push_back(x: param); |
974 | } |
975 | } |
976 | } |
977 | if (params.size() && decl) |
978 | decl->setParams(params); |
979 | |
980 | m_uid_to_decl[sym_id] = decl; |
981 | |
982 | return decl; |
983 | } |
984 | default: { |
985 | // It's not a variable and not a function, check if it's a type |
986 | Type *type = symbol_file->ResolveTypeUID(type_uid: sym_id); |
987 | if (!type) |
988 | return nullptr; |
989 | |
990 | return m_uid_to_decl.lookup(Val: sym_id); |
991 | } |
992 | } |
993 | } |
994 | |
995 | clang::DeclContext * |
996 | PDBASTParser::GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol) { |
997 | if (symbol.getSymTag() == PDB_SymType::Function) { |
998 | clang::DeclContext *result = |
999 | llvm::dyn_cast_or_null<clang::FunctionDecl>(Val: GetDeclForSymbol(symbol)); |
1000 | |
1001 | if (result) |
1002 | m_decl_context_to_uid[result] = symbol.getSymIndexId(); |
1003 | |
1004 | return result; |
1005 | } |
1006 | |
1007 | auto symbol_file = static_cast<SymbolFilePDB *>( |
1008 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
1009 | if (!symbol_file) |
1010 | return nullptr; |
1011 | |
1012 | auto type = symbol_file->ResolveTypeUID(type_uid: symbol.getSymIndexId()); |
1013 | if (!type) |
1014 | return nullptr; |
1015 | |
1016 | clang::DeclContext *result = |
1017 | m_ast.GetDeclContextForType(type: type->GetForwardCompilerType()); |
1018 | |
1019 | if (result) |
1020 | m_decl_context_to_uid[result] = symbol.getSymIndexId(); |
1021 | |
1022 | return result; |
1023 | } |
1024 | |
1025 | clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol( |
1026 | const llvm::pdb::PDBSymbol &symbol) { |
1027 | auto parent = GetClassOrFunctionParent(symbol); |
1028 | while (parent) { |
1029 | if (auto parent_context = GetDeclContextForSymbol(symbol: *parent)) |
1030 | return parent_context; |
1031 | |
1032 | parent = GetClassOrFunctionParent(symbol: *parent); |
1033 | } |
1034 | |
1035 | // We can't find any class or function parent of the symbol. So analyze |
1036 | // the full symbol name. The symbol may be belonging to a namespace |
1037 | // or function (or even to a class if it's e.g. a static variable symbol). |
1038 | |
1039 | // TODO: Make clang to emit full names for variables in namespaces |
1040 | // (as MSVC does) |
1041 | |
1042 | std::string name(symbol.getRawSymbol().getName()); |
1043 | MSVCUndecoratedNameParser parser(name); |
1044 | llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); |
1045 | if (specs.empty()) |
1046 | return m_ast.GetTranslationUnitDecl(); |
1047 | |
1048 | auto symbol_file = static_cast<SymbolFilePDB *>( |
1049 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
1050 | if (!symbol_file) |
1051 | return m_ast.GetTranslationUnitDecl(); |
1052 | |
1053 | auto global = symbol_file->GetPDBSession().getGlobalScope(); |
1054 | if (!global) |
1055 | return m_ast.GetTranslationUnitDecl(); |
1056 | |
1057 | bool has_type_or_function_parent = false; |
1058 | clang::DeclContext *curr_context = m_ast.GetTranslationUnitDecl(); |
1059 | for (std::size_t i = 0; i < specs.size() - 1; i++) { |
1060 | // Check if there is a function or a type with the current context's name. |
1061 | if (std::unique_ptr<IPDBEnumSymbols> children_enum = global->findChildren( |
1062 | Type: PDB_SymType::None, Name: specs[i].GetFullName(), Flags: NS_CaseSensitive)) { |
1063 | while (IPDBEnumChildren<PDBSymbol>::ChildTypePtr child = |
1064 | children_enum->getNext()) { |
1065 | if (clang::DeclContext *child_context = |
1066 | GetDeclContextForSymbol(symbol: *child)) { |
1067 | // Note that `GetDeclContextForSymbol' retrieves |
1068 | // a declaration context for functions and types only, |
1069 | // so if we are here then `child_context' is guaranteed |
1070 | // a function or a type declaration context. |
1071 | has_type_or_function_parent = true; |
1072 | curr_context = child_context; |
1073 | } |
1074 | } |
1075 | } |
1076 | |
1077 | // If there were no functions or types above then retrieve a namespace with |
1078 | // the current context's name. There can be no namespaces inside a function |
1079 | // or a type. We check it to avoid fake namespaces such as `__l2': |
1080 | // `N0::N1::CClass::PrivateFunc::__l2::InnerFuncStruct' |
1081 | if (!has_type_or_function_parent) { |
1082 | std::string namespace_name = std::string(specs[i].GetBaseName()); |
1083 | const char *namespace_name_c_str = |
1084 | IsAnonymousNamespaceName(name: namespace_name) ? nullptr |
1085 | : namespace_name.data(); |
1086 | clang::NamespaceDecl *namespace_decl = |
1087 | m_ast.GetUniqueNamespaceDeclaration( |
1088 | name: namespace_name_c_str, decl_ctx: curr_context, owning_module: OptionalClangModuleID()); |
1089 | |
1090 | m_parent_to_namespaces[curr_context].insert(x: namespace_decl); |
1091 | m_namespaces.insert(x: namespace_decl); |
1092 | |
1093 | curr_context = namespace_decl; |
1094 | } |
1095 | } |
1096 | |
1097 | return curr_context; |
1098 | } |
1099 | |
1100 | void PDBASTParser::ParseDeclsForDeclContext( |
1101 | const clang::DeclContext *decl_context) { |
1102 | auto symbol_file = static_cast<SymbolFilePDB *>( |
1103 | m_ast.GetSymbolFile()->GetBackingSymbolFile()); |
1104 | if (!symbol_file) |
1105 | return; |
1106 | |
1107 | IPDBSession &session = symbol_file->GetPDBSession(); |
1108 | auto symbol_up = |
1109 | session.getSymbolById(SymbolId: m_decl_context_to_uid.lookup(Val: decl_context)); |
1110 | auto global_up = session.getGlobalScope(); |
1111 | |
1112 | PDBSymbol *symbol; |
1113 | if (symbol_up) |
1114 | symbol = symbol_up.get(); |
1115 | else if (global_up) |
1116 | symbol = global_up.get(); |
1117 | else |
1118 | return; |
1119 | |
1120 | if (auto children = symbol->findAllChildren()) |
1121 | while (auto child = children->getNext()) |
1122 | GetDeclForSymbol(symbol: *child); |
1123 | } |
1124 | |
1125 | clang::NamespaceDecl * |
1126 | PDBASTParser::FindNamespaceDecl(const clang::DeclContext *parent, |
1127 | llvm::StringRef name) { |
1128 | NamespacesSet *set; |
1129 | if (parent) { |
1130 | auto pit = m_parent_to_namespaces.find(Val: parent); |
1131 | if (pit == m_parent_to_namespaces.end()) |
1132 | return nullptr; |
1133 | |
1134 | set = &pit->second; |
1135 | } else { |
1136 | set = &m_namespaces; |
1137 | } |
1138 | assert(set); |
1139 | |
1140 | for (clang::NamespaceDecl *namespace_decl : *set) |
1141 | if (namespace_decl->getName() == name) |
1142 | return namespace_decl; |
1143 | |
1144 | for (clang::NamespaceDecl *namespace_decl : *set) |
1145 | if (namespace_decl->isAnonymousNamespace()) |
1146 | return FindNamespaceDecl(namespace_decl, name); |
1147 | |
1148 | return nullptr; |
1149 | } |
1150 | |
1151 | bool PDBASTParser::AddEnumValue(CompilerType enum_type, |
1152 | const PDBSymbolData &enum_value) { |
1153 | Declaration decl; |
1154 | Variant v = enum_value.getValue(); |
1155 | std::string name = |
1156 | std::string(MSVCUndecoratedNameParser::DropScope(name: enum_value.getName())); |
1157 | uint64_t raw_value; |
1158 | switch (v.Type) { |
1159 | case PDB_VariantType::Int8: |
1160 | raw_value = v.Value.Int8; |
1161 | break; |
1162 | case PDB_VariantType::Int16: |
1163 | raw_value = v.Value.Int16; |
1164 | break; |
1165 | case PDB_VariantType::Int32: |
1166 | raw_value = v.Value.Int32; |
1167 | break; |
1168 | case PDB_VariantType::Int64: |
1169 | raw_value = v.Value.Int64; |
1170 | break; |
1171 | case PDB_VariantType::UInt8: |
1172 | raw_value = v.Value.UInt8; |
1173 | break; |
1174 | case PDB_VariantType::UInt16: |
1175 | raw_value = v.Value.UInt16; |
1176 | break; |
1177 | case PDB_VariantType::UInt32: |
1178 | raw_value = v.Value.UInt32; |
1179 | break; |
1180 | case PDB_VariantType::UInt64: |
1181 | raw_value = v.Value.UInt64; |
1182 | break; |
1183 | default: |
1184 | return false; |
1185 | } |
1186 | CompilerType underlying_type = m_ast.GetEnumerationIntegerType(type: enum_type); |
1187 | uint32_t byte_size = m_ast.getASTContext().getTypeSize( |
1188 | T: ClangUtil::GetQualType(ct: underlying_type)); |
1189 | auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType( |
1190 | enum_type, decl, name: name.c_str(), enum_value: raw_value, enum_value_bit_size: byte_size * 8); |
1191 | if (!enum_constant_decl) |
1192 | return false; |
1193 | |
1194 | m_uid_to_decl[enum_value.getSymIndexId()] = enum_constant_decl; |
1195 | |
1196 | return true; |
1197 | } |
1198 | |
1199 | bool PDBASTParser::CompleteTypeFromUDT( |
1200 | lldb_private::SymbolFile &symbol_file, |
1201 | lldb_private::CompilerType &compiler_type, |
1202 | llvm::pdb::PDBSymbolTypeUDT &udt) { |
1203 | ClangASTImporter::LayoutInfo layout_info; |
1204 | layout_info.bit_size = udt.getLength() * 8; |
1205 | |
1206 | auto nested_enums = udt.findAllChildren<PDBSymbolTypeUDT>(); |
1207 | if (nested_enums) |
1208 | while (auto nested = nested_enums->getNext()) |
1209 | symbol_file.ResolveTypeUID(type_uid: nested->getSymIndexId()); |
1210 | |
1211 | auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>(); |
1212 | if (bases_enum) |
1213 | AddRecordBases(symbol_file, record_type&: compiler_type, |
1214 | record_kind: TranslateUdtKind(pdb_kind: udt.getUdtKind()), bases_enum&: *bases_enum, |
1215 | layout_info); |
1216 | |
1217 | auto members_enum = udt.findAllChildren<PDBSymbolData>(); |
1218 | if (members_enum) |
1219 | AddRecordMembers(symbol_file, record_type&: compiler_type, members_enum&: *members_enum, layout_info); |
1220 | |
1221 | auto methods_enum = udt.findAllChildren<PDBSymbolFunc>(); |
1222 | if (methods_enum) |
1223 | AddRecordMethods(symbol_file, record_type&: compiler_type, methods_enum&: *methods_enum); |
1224 | |
1225 | m_ast.AddMethodOverridesForCXXRecordType(type: compiler_type.GetOpaqueQualType()); |
1226 | TypeSystemClang::BuildIndirectFields(type: compiler_type); |
1227 | TypeSystemClang::CompleteTagDeclarationDefinition(type: compiler_type); |
1228 | |
1229 | clang::CXXRecordDecl *record_decl = |
1230 | m_ast.GetAsCXXRecordDecl(type: compiler_type.GetOpaqueQualType()); |
1231 | if (!record_decl) |
1232 | return static_cast<bool>(compiler_type); |
1233 | |
1234 | GetClangASTImporter().SetRecordLayout(record_decl, layout_info); |
1235 | |
1236 | return static_cast<bool>(compiler_type); |
1237 | } |
1238 | |
1239 | void PDBASTParser::AddRecordMembers( |
1240 | lldb_private::SymbolFile &symbol_file, |
1241 | lldb_private::CompilerType &record_type, |
1242 | PDBDataSymbolEnumerator &members_enum, |
1243 | lldb_private::ClangASTImporter::LayoutInfo &layout_info) { |
1244 | while (auto member = members_enum.getNext()) { |
1245 | if (member->isCompilerGenerated()) |
1246 | continue; |
1247 | |
1248 | auto member_name = member->getName(); |
1249 | |
1250 | auto member_type = symbol_file.ResolveTypeUID(type_uid: member->getTypeId()); |
1251 | if (!member_type) |
1252 | continue; |
1253 | |
1254 | auto member_comp_type = member_type->GetLayoutCompilerType(); |
1255 | if (!member_comp_type.GetCompleteType()) { |
1256 | symbol_file.GetObjectFile()->GetModule()->ReportError( |
1257 | format: ":: Class '{0}' has a member '{1}' of type '{2}' " |
1258 | "which does not have a complete definition." , |
1259 | args: record_type.GetTypeName().GetCString(), args: member_name.c_str(), |
1260 | args: member_comp_type.GetTypeName().GetCString()); |
1261 | if (TypeSystemClang::StartTagDeclarationDefinition(type: member_comp_type)) |
1262 | TypeSystemClang::CompleteTagDeclarationDefinition(type: member_comp_type); |
1263 | } |
1264 | |
1265 | auto access = TranslateMemberAccess(access: member->getAccess()); |
1266 | |
1267 | switch (member->getDataKind()) { |
1268 | case PDB_DataKind::Member: { |
1269 | auto location_type = member->getLocationType(); |
1270 | |
1271 | auto bit_size = member->getLength(); |
1272 | if (location_type == PDB_LocType::ThisRel) |
1273 | bit_size *= 8; |
1274 | |
1275 | auto decl = TypeSystemClang::AddFieldToRecordType( |
1276 | type: record_type, name: member_name.c_str(), field_type: member_comp_type, access, bitfield_bit_size: bit_size); |
1277 | if (!decl) |
1278 | continue; |
1279 | |
1280 | m_uid_to_decl[member->getSymIndexId()] = decl; |
1281 | |
1282 | auto offset = member->getOffset() * 8; |
1283 | if (location_type == PDB_LocType::BitField) |
1284 | offset += member->getBitPosition(); |
1285 | |
1286 | layout_info.field_offsets.insert(KV: std::make_pair(x&: decl, y&: offset)); |
1287 | |
1288 | break; |
1289 | } |
1290 | case PDB_DataKind::StaticMember: { |
1291 | auto decl = TypeSystemClang::AddVariableToRecordType( |
1292 | type: record_type, name: member_name.c_str(), var_type: member_comp_type, access); |
1293 | if (!decl) |
1294 | continue; |
1295 | |
1296 | // Static constant members may be a const[expr] declaration. |
1297 | // Query the symbol's value as the variable initializer if valid. |
1298 | if (member_comp_type.IsConst()) { |
1299 | auto value = member->getValue(); |
1300 | if (value.Type == llvm::pdb::Empty) { |
1301 | LLDB_LOG(GetLog(LLDBLog::AST), |
1302 | "Class '{0}' has member '{1}' of type '{2}' with an unknown " |
1303 | "constant size." , |
1304 | record_type.GetTypeName(), member_name, |
1305 | member_comp_type.GetTypeName()); |
1306 | continue; |
1307 | } |
1308 | |
1309 | clang::QualType qual_type = decl->getType(); |
1310 | unsigned type_width = m_ast.getASTContext().getIntWidth(T: qual_type); |
1311 | unsigned constant_width = value.getBitWidth(); |
1312 | |
1313 | if (qual_type->isIntegralOrEnumerationType()) { |
1314 | if (type_width >= constant_width) { |
1315 | TypeSystemClang::SetIntegerInitializerForVariable( |
1316 | var: decl, init_value: value.toAPSInt().extOrTrunc(width: type_width)); |
1317 | } else { |
1318 | LLDB_LOG(GetLog(LLDBLog::AST), |
1319 | "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) " |
1320 | "which resolves to a wider constant value ({4} bits). " |
1321 | "Ignoring constant." , |
1322 | record_type.GetTypeName(), member_name, |
1323 | member_comp_type.GetTypeName(), type_width, |
1324 | constant_width); |
1325 | } |
1326 | } else { |
1327 | switch (member_comp_type.GetBasicTypeEnumeration()) { |
1328 | case lldb::eBasicTypeFloat: |
1329 | case lldb::eBasicTypeDouble: |
1330 | case lldb::eBasicTypeLongDouble: |
1331 | if (type_width == constant_width) { |
1332 | TypeSystemClang::SetFloatingInitializerForVariable( |
1333 | var: decl, init_value: value.toAPFloat()); |
1334 | decl->setConstexpr(true); |
1335 | } else { |
1336 | LLDB_LOG(GetLog(LLDBLog::AST), |
1337 | "Class '{0}' has a member '{1}' of type '{2}' ({3} " |
1338 | "bits) which resolves to a constant value of mismatched " |
1339 | "width ({4} bits). Ignoring constant." , |
1340 | record_type.GetTypeName(), member_name, |
1341 | member_comp_type.GetTypeName(), type_width, |
1342 | constant_width); |
1343 | } |
1344 | break; |
1345 | default: |
1346 | break; |
1347 | } |
1348 | } |
1349 | } |
1350 | |
1351 | m_uid_to_decl[member->getSymIndexId()] = decl; |
1352 | |
1353 | break; |
1354 | } |
1355 | default: |
1356 | llvm_unreachable("unsupported PDB data kind" ); |
1357 | } |
1358 | } |
1359 | } |
1360 | |
1361 | void PDBASTParser::AddRecordBases( |
1362 | lldb_private::SymbolFile &symbol_file, |
1363 | lldb_private::CompilerType &record_type, int record_kind, |
1364 | PDBBaseClassSymbolEnumerator &bases_enum, |
1365 | lldb_private::ClangASTImporter::LayoutInfo &layout_info) const { |
1366 | std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> base_classes; |
1367 | |
1368 | while (auto base = bases_enum.getNext()) { |
1369 | auto base_type = symbol_file.ResolveTypeUID(type_uid: base->getTypeId()); |
1370 | if (!base_type) |
1371 | continue; |
1372 | |
1373 | auto base_comp_type = base_type->GetFullCompilerType(); |
1374 | if (!base_comp_type.GetCompleteType()) { |
1375 | symbol_file.GetObjectFile()->GetModule()->ReportError( |
1376 | format: ":: Class '{0}' has a base class '{1}' " |
1377 | "which does not have a complete definition." , |
1378 | args: record_type.GetTypeName().GetCString(), |
1379 | args: base_comp_type.GetTypeName().GetCString()); |
1380 | if (TypeSystemClang::StartTagDeclarationDefinition(type: base_comp_type)) |
1381 | TypeSystemClang::CompleteTagDeclarationDefinition(type: base_comp_type); |
1382 | } |
1383 | |
1384 | auto access = TranslateMemberAccess(access: base->getAccess()); |
1385 | |
1386 | auto is_virtual = base->isVirtualBaseClass(); |
1387 | |
1388 | std::unique_ptr<clang::CXXBaseSpecifier> base_spec = |
1389 | m_ast.CreateBaseClassSpecifier( |
1390 | type: base_comp_type.GetOpaqueQualType(), access, is_virtual, |
1391 | base_of_class: record_kind == llvm::to_underlying(E: clang::TagTypeKind::Class)); |
1392 | lldbassert(base_spec); |
1393 | |
1394 | base_classes.push_back(x: std::move(base_spec)); |
1395 | |
1396 | if (is_virtual) |
1397 | continue; |
1398 | |
1399 | auto decl = m_ast.GetAsCXXRecordDecl(type: base_comp_type.GetOpaqueQualType()); |
1400 | if (!decl) |
1401 | continue; |
1402 | |
1403 | auto offset = clang::CharUnits::fromQuantity(Quantity: base->getOffset()); |
1404 | layout_info.base_offsets.insert(KV: std::make_pair(x&: decl, y&: offset)); |
1405 | } |
1406 | |
1407 | m_ast.TransferBaseClasses(type: record_type.GetOpaqueQualType(), |
1408 | bases: std::move(base_classes)); |
1409 | } |
1410 | |
1411 | void PDBASTParser::AddRecordMethods(lldb_private::SymbolFile &symbol_file, |
1412 | lldb_private::CompilerType &record_type, |
1413 | PDBFuncSymbolEnumerator &methods_enum) { |
1414 | while (std::unique_ptr<PDBSymbolFunc> method = methods_enum.getNext()) |
1415 | if (clang::CXXMethodDecl *decl = |
1416 | AddRecordMethod(symbol_file, record_type, method: *method)) |
1417 | m_uid_to_decl[method->getSymIndexId()] = decl; |
1418 | } |
1419 | |
1420 | clang::CXXMethodDecl * |
1421 | PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, |
1422 | lldb_private::CompilerType &record_type, |
1423 | const llvm::pdb::PDBSymbolFunc &method) const { |
1424 | std::string name = |
1425 | std::string(MSVCUndecoratedNameParser::DropScope(name: method.getName())); |
1426 | |
1427 | Type *method_type = symbol_file.ResolveTypeUID(type_uid: method.getSymIndexId()); |
1428 | // MSVC specific __vecDelDtor. |
1429 | if (!method_type) |
1430 | return nullptr; |
1431 | |
1432 | CompilerType method_comp_type = method_type->GetFullCompilerType(); |
1433 | if (!method_comp_type.GetCompleteType()) { |
1434 | symbol_file.GetObjectFile()->GetModule()->ReportError( |
1435 | format: ":: Class '{0}' has a method '{1}' whose type cannot be completed." , |
1436 | args: record_type.GetTypeName().GetCString(), |
1437 | args: method_comp_type.GetTypeName().GetCString()); |
1438 | if (TypeSystemClang::StartTagDeclarationDefinition(type: method_comp_type)) |
1439 | TypeSystemClang::CompleteTagDeclarationDefinition(type: method_comp_type); |
1440 | } |
1441 | |
1442 | AccessType access = TranslateMemberAccess(access: method.getAccess()); |
1443 | if (access == eAccessNone) |
1444 | access = eAccessPublic; |
1445 | |
1446 | // TODO: get mangled name for the method. |
1447 | return m_ast.AddMethodToCXXRecordType( |
1448 | type: record_type.GetOpaqueQualType(), name: name.c_str(), |
1449 | /*mangled_name*/ nullptr, method_type: method_comp_type, access, is_virtual: method.isVirtual(), |
1450 | is_static: method.isStatic(), is_inline: method.hasInlineAttribute(), |
1451 | /*is_explicit*/ false, // FIXME: Need this field in CodeView. |
1452 | /*is_attr_used*/ false, |
1453 | /*is_artificial*/ method.isCompilerGenerated()); |
1454 | } |
1455 | |