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