| 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 | |