File: | src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp |
Warning: | line 1127, column 50 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- SymbolFilePDB.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 "SymbolFilePDB.h" | |||
10 | ||||
11 | #include "PDBASTParser.h" | |||
12 | #include "PDBLocationToDWARFExpression.h" | |||
13 | ||||
14 | #include "clang/Lex/Lexer.h" | |||
15 | ||||
16 | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" | |||
17 | #include "lldb/Core/Module.h" | |||
18 | #include "lldb/Core/PluginManager.h" | |||
19 | #include "lldb/Symbol/CompileUnit.h" | |||
20 | #include "lldb/Symbol/LineTable.h" | |||
21 | #include "lldb/Symbol/ObjectFile.h" | |||
22 | #include "lldb/Symbol/SymbolContext.h" | |||
23 | #include "lldb/Symbol/SymbolVendor.h" | |||
24 | #include "lldb/Symbol/TypeList.h" | |||
25 | #include "lldb/Symbol/TypeMap.h" | |||
26 | #include "lldb/Symbol/Variable.h" | |||
27 | #include "lldb/Utility/Log.h" | |||
28 | #include "lldb/Utility/RegularExpression.h" | |||
29 | ||||
30 | #include "llvm/DebugInfo/PDB/GenericError.h" | |||
31 | #include "llvm/DebugInfo/PDB/IPDBDataStream.h" | |||
32 | #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" | |||
33 | #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" | |||
34 | #include "llvm/DebugInfo/PDB/IPDBSectionContrib.h" | |||
35 | #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" | |||
36 | #include "llvm/DebugInfo/PDB/IPDBTable.h" | |||
37 | #include "llvm/DebugInfo/PDB/PDBSymbol.h" | |||
38 | #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" | |||
39 | #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" | |||
40 | #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" | |||
41 | #include "llvm/DebugInfo/PDB/PDBSymbolData.h" | |||
42 | #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" | |||
43 | #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" | |||
44 | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" | |||
45 | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" | |||
46 | #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" | |||
47 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" | |||
48 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" | |||
49 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" | |||
50 | ||||
51 | #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" | |||
52 | #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" | |||
53 | #include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h" | |||
54 | ||||
55 | using namespace lldb; | |||
56 | using namespace lldb_private; | |||
57 | using namespace llvm::pdb; | |||
58 | ||||
59 | LLDB_PLUGIN_DEFINE(SymbolFilePDB)namespace lldb_private { void lldb_initialize_SymbolFilePDB() { SymbolFilePDB::Initialize(); } void lldb_terminate_SymbolFilePDB () { SymbolFilePDB::Terminate(); } } | |||
60 | ||||
61 | char SymbolFilePDB::ID; | |||
62 | ||||
63 | namespace { | |||
64 | lldb::LanguageType TranslateLanguage(PDB_Lang lang) { | |||
65 | switch (lang) { | |||
66 | case PDB_Lang::Cpp: | |||
67 | return lldb::LanguageType::eLanguageTypeC_plus_plus; | |||
68 | case PDB_Lang::C: | |||
69 | return lldb::LanguageType::eLanguageTypeC; | |||
70 | case PDB_Lang::Swift: | |||
71 | return lldb::LanguageType::eLanguageTypeSwift; | |||
72 | default: | |||
73 | return lldb::LanguageType::eLanguageTypeUnknown; | |||
74 | } | |||
75 | } | |||
76 | ||||
77 | bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line, | |||
78 | uint32_t addr_length) { | |||
79 | return ((requested_line == 0 || actual_line == requested_line) && | |||
80 | addr_length > 0); | |||
81 | } | |||
82 | } // namespace | |||
83 | ||||
84 | static bool ShouldUseNativeReader() { | |||
85 | #if defined(_WIN32) | |||
86 | llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER"); | |||
87 | return use_native.equals_insensitive("on") || | |||
88 | use_native.equals_insensitive("yes") || | |||
89 | use_native.equals_insensitive("1") || | |||
90 | use_native.equals_insensitive("true"); | |||
91 | #else | |||
92 | return true; | |||
93 | #endif | |||
94 | } | |||
95 | ||||
96 | void SymbolFilePDB::Initialize() { | |||
97 | if (ShouldUseNativeReader()) { | |||
98 | npdb::SymbolFileNativePDB::Initialize(); | |||
99 | } else { | |||
100 | PluginManager::RegisterPlugin(GetPluginNameStatic(), | |||
101 | GetPluginDescriptionStatic(), CreateInstance, | |||
102 | DebuggerInitialize); | |||
103 | } | |||
104 | } | |||
105 | ||||
106 | void SymbolFilePDB::Terminate() { | |||
107 | if (ShouldUseNativeReader()) { | |||
108 | npdb::SymbolFileNativePDB::Terminate(); | |||
109 | } else { | |||
110 | PluginManager::UnregisterPlugin(CreateInstance); | |||
111 | } | |||
112 | } | |||
113 | ||||
114 | void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {} | |||
115 | ||||
116 | lldb_private::ConstString SymbolFilePDB::GetPluginNameStatic() { | |||
117 | static ConstString g_name("pdb"); | |||
118 | return g_name; | |||
119 | } | |||
120 | ||||
121 | const char *SymbolFilePDB::GetPluginDescriptionStatic() { | |||
122 | return "Microsoft PDB debug symbol file reader."; | |||
123 | } | |||
124 | ||||
125 | lldb_private::SymbolFile * | |||
126 | SymbolFilePDB::CreateInstance(ObjectFileSP objfile_sp) { | |||
127 | return new SymbolFilePDB(std::move(objfile_sp)); | |||
128 | } | |||
129 | ||||
130 | SymbolFilePDB::SymbolFilePDB(lldb::ObjectFileSP objfile_sp) | |||
131 | : SymbolFile(std::move(objfile_sp)), m_session_up(), m_global_scope_up() {} | |||
132 | ||||
133 | SymbolFilePDB::~SymbolFilePDB() = default; | |||
134 | ||||
135 | uint32_t SymbolFilePDB::CalculateAbilities() { | |||
136 | uint32_t abilities = 0; | |||
137 | if (!m_objfile_sp) | |||
138 | return 0; | |||
139 | ||||
140 | if (!m_session_up) { | |||
141 | // Lazily load and match the PDB file, but only do this once. | |||
142 | std::string exePath = m_objfile_sp->GetFileSpec().GetPath(); | |||
143 | auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath), | |||
144 | m_session_up); | |||
145 | if (error) { | |||
146 | llvm::consumeError(std::move(error)); | |||
147 | auto module_sp = m_objfile_sp->GetModule(); | |||
148 | if (!module_sp) | |||
149 | return 0; | |||
150 | // See if any symbol file is specified through `--symfile` option. | |||
151 | FileSpec symfile = module_sp->GetSymbolFileFileSpec(); | |||
152 | if (!symfile) | |||
153 | return 0; | |||
154 | error = loadDataForPDB(PDB_ReaderType::DIA, | |||
155 | llvm::StringRef(symfile.GetPath()), m_session_up); | |||
156 | if (error) { | |||
157 | llvm::consumeError(std::move(error)); | |||
158 | return 0; | |||
159 | } | |||
160 | } | |||
161 | } | |||
162 | if (!m_session_up) | |||
163 | return 0; | |||
164 | ||||
165 | auto enum_tables_up = m_session_up->getEnumTables(); | |||
166 | if (!enum_tables_up) | |||
167 | return 0; | |||
168 | while (auto table_up = enum_tables_up->getNext()) { | |||
169 | if (table_up->getItemCount() == 0) | |||
170 | continue; | |||
171 | auto type = table_up->getTableType(); | |||
172 | switch (type) { | |||
173 | case PDB_TableType::Symbols: | |||
174 | // This table represents a store of symbols with types listed in | |||
175 | // PDBSym_Type | |||
176 | abilities |= (CompileUnits | Functions | Blocks | GlobalVariables | | |||
177 | LocalVariables | VariableTypes); | |||
178 | break; | |||
179 | case PDB_TableType::LineNumbers: | |||
180 | abilities |= LineTables; | |||
181 | break; | |||
182 | default: | |||
183 | break; | |||
184 | } | |||
185 | } | |||
186 | return abilities; | |||
187 | } | |||
188 | ||||
189 | void SymbolFilePDB::InitializeObject() { | |||
190 | lldb::addr_t obj_load_address = | |||
191 | m_objfile_sp->GetBaseAddress().GetFileAddress(); | |||
192 | lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS)lldb_private::lldb_assert(static_cast<bool>(obj_load_address && obj_load_address != 0xffffffffffffffffULL), "obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS" , __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 192); | |||
193 | m_session_up->setLoadAddress(obj_load_address); | |||
194 | if (!m_global_scope_up) | |||
195 | m_global_scope_up = m_session_up->getGlobalScope(); | |||
196 | lldbassert(m_global_scope_up.get())lldb_private::lldb_assert(static_cast<bool>(m_global_scope_up .get()), "m_global_scope_up.get()", __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 196); | |||
197 | } | |||
198 | ||||
199 | uint32_t SymbolFilePDB::CalculateNumCompileUnits() { | |||
200 | auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); | |||
201 | if (!compilands) | |||
202 | return 0; | |||
203 | ||||
204 | // The linker could link *.dll (compiland language = LINK), or import | |||
205 | // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be | |||
206 | // found as a child of the global scope (PDB executable). Usually, such | |||
207 | // compilands contain `thunk` symbols in which we are not interested for | |||
208 | // now. However we still count them in the compiland list. If we perform | |||
209 | // any compiland related activity, like finding symbols through | |||
210 | // llvm::pdb::IPDBSession methods, such compilands will all be searched | |||
211 | // automatically no matter whether we include them or not. | |||
212 | uint32_t compile_unit_count = compilands->getChildCount(); | |||
213 | ||||
214 | // The linker can inject an additional "dummy" compilation unit into the | |||
215 | // PDB. Ignore this special compile unit for our purposes, if it is there. | |||
216 | // It is always the last one. | |||
217 | auto last_compiland_up = compilands->getChildAtIndex(compile_unit_count - 1); | |||
218 | lldbassert(last_compiland_up.get())lldb_private::lldb_assert(static_cast<bool>(last_compiland_up .get()), "last_compiland_up.get()", __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 218); | |||
219 | std::string name = last_compiland_up->getName(); | |||
220 | if (name == "* Linker *") | |||
221 | --compile_unit_count; | |||
222 | return compile_unit_count; | |||
223 | } | |||
224 | ||||
225 | void SymbolFilePDB::GetCompileUnitIndex( | |||
226 | const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index) { | |||
227 | auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); | |||
228 | if (!results_up) | |||
229 | return; | |||
230 | auto uid = pdb_compiland.getSymIndexId(); | |||
231 | for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { | |||
232 | auto compiland_up = results_up->getChildAtIndex(cu_idx); | |||
233 | if (!compiland_up) | |||
234 | continue; | |||
235 | if (compiland_up->getSymIndexId() == uid) { | |||
236 | index = cu_idx; | |||
237 | return; | |||
238 | } | |||
239 | } | |||
240 | index = UINT32_MAX0xffffffffU; | |||
241 | return; | |||
242 | } | |||
243 | ||||
244 | std::unique_ptr<llvm::pdb::PDBSymbolCompiland> | |||
245 | SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) { | |||
246 | return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid); | |||
247 | } | |||
248 | ||||
249 | lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) { | |||
250 | if (index >= GetNumCompileUnits()) | |||
251 | return CompUnitSP(); | |||
252 | ||||
253 | // Assuming we always retrieve same compilands listed in same order through | |||
254 | // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a | |||
255 | // compile unit makes no sense. | |||
256 | auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); | |||
257 | if (!results) | |||
258 | return CompUnitSP(); | |||
259 | auto compiland_up = results->getChildAtIndex(index); | |||
260 | if (!compiland_up) | |||
261 | return CompUnitSP(); | |||
262 | return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index); | |||
263 | } | |||
264 | ||||
265 | lldb::LanguageType SymbolFilePDB::ParseLanguage(CompileUnit &comp_unit) { | |||
266 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
267 | auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); | |||
268 | if (!compiland_up) | |||
269 | return lldb::eLanguageTypeUnknown; | |||
270 | auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>(); | |||
271 | if (!details) | |||
272 | return lldb::eLanguageTypeUnknown; | |||
273 | return TranslateLanguage(details->getLanguage()); | |||
274 | } | |||
275 | ||||
276 | lldb_private::Function * | |||
277 | SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, | |||
278 | CompileUnit &comp_unit) { | |||
279 | if (FunctionSP result = comp_unit.FindFunctionByUID(pdb_func.getSymIndexId())) | |||
280 | return result.get(); | |||
281 | ||||
282 | auto file_vm_addr = pdb_func.getVirtualAddress(); | |||
283 | if (file_vm_addr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL || file_vm_addr == 0) | |||
284 | return nullptr; | |||
285 | ||||
286 | auto func_length = pdb_func.getLength(); | |||
287 | AddressRange func_range = | |||
288 | AddressRange(file_vm_addr, func_length, | |||
289 | GetObjectFile()->GetModule()->GetSectionList()); | |||
290 | if (!func_range.GetBaseAddress().IsValid()) | |||
291 | return nullptr; | |||
292 | ||||
293 | lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId()); | |||
294 | if (!func_type) | |||
295 | return nullptr; | |||
296 | ||||
297 | user_id_t func_type_uid = pdb_func.getSignatureId(); | |||
298 | ||||
299 | Mangled mangled = GetMangledForPDBFunc(pdb_func); | |||
300 | ||||
301 | FunctionSP func_sp = | |||
302 | std::make_shared<Function>(&comp_unit, pdb_func.getSymIndexId(), | |||
303 | func_type_uid, mangled, func_type, func_range); | |||
304 | ||||
305 | comp_unit.AddFunction(func_sp); | |||
306 | ||||
307 | LanguageType lang = ParseLanguage(comp_unit); | |||
308 | auto type_system_or_err = GetTypeSystemForLanguage(lang); | |||
309 | if (auto err = type_system_or_err.takeError()) { | |||
310 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to parse PDBFunc"); } else ::llvm::consumeError (::std::move(error_private)); } while (0) | |||
311 | std::move(err), "Unable to parse PDBFunc")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to parse PDBFunc"); } else ::llvm::consumeError (::std::move(error_private)); } while (0); | |||
312 | return nullptr; | |||
313 | } | |||
314 | ||||
315 | TypeSystemClang *clang_type_system = | |||
316 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
317 | if (!clang_type_system) | |||
318 | return nullptr; | |||
319 | clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func); | |||
320 | ||||
321 | return func_sp.get(); | |||
322 | } | |||
323 | ||||
324 | size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) { | |||
325 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
326 | size_t func_added = 0; | |||
327 | auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); | |||
328 | if (!compiland_up) | |||
329 | return 0; | |||
330 | auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>(); | |||
331 | if (!results_up) | |||
332 | return 0; | |||
333 | while (auto pdb_func_up = results_up->getNext()) { | |||
334 | auto func_sp = comp_unit.FindFunctionByUID(pdb_func_up->getSymIndexId()); | |||
335 | if (!func_sp) { | |||
336 | if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, comp_unit)) | |||
337 | ++func_added; | |||
338 | } | |||
339 | } | |||
340 | return func_added; | |||
341 | } | |||
342 | ||||
343 | bool SymbolFilePDB::ParseLineTable(CompileUnit &comp_unit) { | |||
344 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
345 | if (comp_unit.GetLineTable()) | |||
346 | return true; | |||
347 | return ParseCompileUnitLineTable(comp_unit, 0); | |||
348 | } | |||
349 | ||||
350 | bool SymbolFilePDB::ParseDebugMacros(CompileUnit &comp_unit) { | |||
351 | // PDB doesn't contain information about macros | |||
352 | return false; | |||
353 | } | |||
354 | ||||
355 | bool SymbolFilePDB::ParseSupportFiles( | |||
356 | CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) { | |||
357 | ||||
358 | // In theory this is unnecessary work for us, because all of this information | |||
359 | // is easily (and quickly) accessible from DebugInfoPDB, so caching it a | |||
360 | // second time seems like a waste. Unfortunately, there's no good way around | |||
361 | // this short of a moderate refactor since SymbolVendor depends on being able | |||
362 | // to cache this list. | |||
363 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
364 | auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); | |||
365 | if (!compiland_up) | |||
366 | return false; | |||
367 | auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); | |||
368 | if (!files || files->getChildCount() == 0) | |||
369 | return false; | |||
370 | ||||
371 | while (auto file = files->getNext()) { | |||
372 | FileSpec spec(file->getFileName(), FileSpec::Style::windows); | |||
373 | support_files.AppendIfUnique(spec); | |||
374 | } | |||
375 | ||||
376 | return true; | |||
377 | } | |||
378 | ||||
379 | bool SymbolFilePDB::ParseImportedModules( | |||
380 | const lldb_private::SymbolContext &sc, | |||
381 | std::vector<SourceModule> &imported_modules) { | |||
382 | // PDB does not yet support module debug info | |||
383 | return false; | |||
384 | } | |||
385 | ||||
386 | static size_t ParseFunctionBlocksForPDBSymbol( | |||
387 | uint64_t func_file_vm_addr, const llvm::pdb::PDBSymbol *pdb_symbol, | |||
388 | lldb_private::Block *parent_block, bool is_top_parent) { | |||
389 | assert(pdb_symbol && parent_block)((void)0); | |||
390 | ||||
391 | size_t num_added = 0; | |||
392 | switch (pdb_symbol->getSymTag()) { | |||
393 | case PDB_SymType::Block: | |||
394 | case PDB_SymType::Function: { | |||
395 | Block *block = nullptr; | |||
396 | auto &raw_sym = pdb_symbol->getRawSymbol(); | |||
397 | if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) { | |||
398 | if (pdb_func->hasNoInlineAttribute()) | |||
399 | break; | |||
400 | if (is_top_parent) | |||
401 | block = parent_block; | |||
402 | else | |||
403 | break; | |||
404 | } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) { | |||
405 | auto uid = pdb_symbol->getSymIndexId(); | |||
406 | if (parent_block->FindBlockByID(uid)) | |||
407 | break; | |||
408 | if (raw_sym.getVirtualAddress() < func_file_vm_addr) | |||
409 | break; | |||
410 | ||||
411 | auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId()); | |||
412 | parent_block->AddChild(block_sp); | |||
413 | block = block_sp.get(); | |||
414 | } else | |||
415 | llvm_unreachable("Unexpected PDB symbol!")__builtin_unreachable(); | |||
416 | ||||
417 | block->AddRange(Block::Range( | |||
418 | raw_sym.getVirtualAddress() - func_file_vm_addr, raw_sym.getLength())); | |||
419 | block->FinalizeRanges(); | |||
420 | ++num_added; | |||
421 | ||||
422 | auto results_up = pdb_symbol->findAllChildren(); | |||
423 | if (!results_up) | |||
424 | break; | |||
425 | while (auto symbol_up = results_up->getNext()) { | |||
426 | num_added += ParseFunctionBlocksForPDBSymbol( | |||
427 | func_file_vm_addr, symbol_up.get(), block, false); | |||
428 | } | |||
429 | } break; | |||
430 | default: | |||
431 | break; | |||
432 | } | |||
433 | return num_added; | |||
434 | } | |||
435 | ||||
436 | size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) { | |||
437 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
438 | size_t num_added = 0; | |||
439 | auto uid = func.GetID(); | |||
440 | auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); | |||
441 | if (!pdb_func_up) | |||
442 | return 0; | |||
443 | Block &parent_block = func.GetBlock(false); | |||
444 | num_added = ParseFunctionBlocksForPDBSymbol( | |||
445 | pdb_func_up->getVirtualAddress(), pdb_func_up.get(), &parent_block, true); | |||
446 | return num_added; | |||
447 | } | |||
448 | ||||
449 | size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) { | |||
450 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
451 | ||||
452 | size_t num_added = 0; | |||
453 | auto compiland = GetPDBCompilandByUID(comp_unit.GetID()); | |||
454 | if (!compiland) | |||
455 | return 0; | |||
456 | ||||
457 | auto ParseTypesByTagFn = [&num_added, this](const PDBSymbol &raw_sym) { | |||
458 | std::unique_ptr<IPDBEnumSymbols> results; | |||
459 | PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef, | |||
460 | PDB_SymType::UDT}; | |||
461 | for (auto tag : tags_to_search) { | |||
462 | results = raw_sym.findAllChildren(tag); | |||
463 | if (!results || results->getChildCount() == 0) | |||
464 | continue; | |||
465 | while (auto symbol = results->getNext()) { | |||
466 | switch (symbol->getSymTag()) { | |||
467 | case PDB_SymType::Enum: | |||
468 | case PDB_SymType::UDT: | |||
469 | case PDB_SymType::Typedef: | |||
470 | break; | |||
471 | default: | |||
472 | continue; | |||
473 | } | |||
474 | ||||
475 | // This should cause the type to get cached and stored in the `m_types` | |||
476 | // lookup. | |||
477 | if (auto type = ResolveTypeUID(symbol->getSymIndexId())) { | |||
478 | // Resolve the type completely to avoid a completion | |||
479 | // (and so a list change, which causes an iterators invalidation) | |||
480 | // during a TypeList dumping | |||
481 | type->GetFullCompilerType(); | |||
482 | ++num_added; | |||
483 | } | |||
484 | } | |||
485 | } | |||
486 | }; | |||
487 | ||||
488 | ParseTypesByTagFn(*compiland); | |||
489 | ||||
490 | // Also parse global types particularly coming from this compiland. | |||
491 | // Unfortunately, PDB has no compiland information for each global type. We | |||
492 | // have to parse them all. But ensure we only do this once. | |||
493 | static bool parse_all_global_types = false; | |||
494 | if (!parse_all_global_types) { | |||
495 | ParseTypesByTagFn(*m_global_scope_up); | |||
496 | parse_all_global_types = true; | |||
497 | } | |||
498 | return num_added; | |||
499 | } | |||
500 | ||||
501 | size_t | |||
502 | SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { | |||
503 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
504 | if (!sc.comp_unit) | |||
505 | return 0; | |||
506 | ||||
507 | size_t num_added = 0; | |||
508 | if (sc.function) { | |||
509 | auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>( | |||
510 | sc.function->GetID()); | |||
511 | if (!pdb_func) | |||
512 | return 0; | |||
513 | ||||
514 | num_added += ParseVariables(sc, *pdb_func); | |||
515 | sc.function->GetBlock(false).SetDidParseVariables(true, true); | |||
516 | } else if (sc.comp_unit) { | |||
517 | auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID()); | |||
518 | if (!compiland) | |||
519 | return 0; | |||
520 | ||||
521 | if (sc.comp_unit->GetVariableList(false)) | |||
522 | return 0; | |||
523 | ||||
524 | auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); | |||
525 | if (results && results->getChildCount()) { | |||
526 | while (auto result = results->getNext()) { | |||
527 | auto cu_id = GetCompilandId(*result); | |||
528 | // FIXME: We are not able to determine variable's compile unit. | |||
529 | if (cu_id == 0) | |||
530 | continue; | |||
531 | ||||
532 | if (cu_id == sc.comp_unit->GetID()) | |||
533 | num_added += ParseVariables(sc, *result); | |||
534 | } | |||
535 | } | |||
536 | ||||
537 | // FIXME: A `file static` or `global constant` variable appears both in | |||
538 | // compiland's children and global scope's children with unexpectedly | |||
539 | // different symbol's Id making it ambiguous. | |||
540 | ||||
541 | // FIXME: 'local constant', for example, const char var[] = "abc", declared | |||
542 | // in a function scope, can't be found in PDB. | |||
543 | ||||
544 | // Parse variables in this compiland. | |||
545 | num_added += ParseVariables(sc, *compiland); | |||
546 | } | |||
547 | ||||
548 | return num_added; | |||
549 | } | |||
550 | ||||
551 | lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { | |||
552 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
553 | auto find_result = m_types.find(type_uid); | |||
554 | if (find_result != m_types.end()) | |||
555 | return find_result->second.get(); | |||
556 | ||||
557 | auto type_system_or_err = | |||
558 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
559 | if (auto err = type_system_or_err.takeError()) { | |||
560 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to ResolveTypeUID"); } else ::llvm::consumeError (::std::move(error_private)); } while (0) | |||
561 | std::move(err), "Unable to ResolveTypeUID")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to ResolveTypeUID"); } else ::llvm::consumeError (::std::move(error_private)); } while (0); | |||
562 | return nullptr; | |||
563 | } | |||
564 | ||||
565 | TypeSystemClang *clang_type_system = | |||
566 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
567 | if (!clang_type_system) | |||
568 | return nullptr; | |||
569 | PDBASTParser *pdb = clang_type_system->GetPDBParser(); | |||
570 | if (!pdb) | |||
571 | return nullptr; | |||
572 | ||||
573 | auto pdb_type = m_session_up->getSymbolById(type_uid); | |||
574 | if (pdb_type == nullptr) | |||
575 | return nullptr; | |||
576 | ||||
577 | lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type); | |||
578 | if (result) { | |||
579 | m_types.insert(std::make_pair(type_uid, result)); | |||
580 | GetTypeList().Insert(result); | |||
581 | } | |||
582 | return result.get(); | |||
583 | } | |||
584 | ||||
585 | llvm::Optional<SymbolFile::ArrayInfo> SymbolFilePDB::GetDynamicArrayInfoForUID( | |||
586 | lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { | |||
587 | return llvm::None; | |||
588 | } | |||
589 | ||||
590 | bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { | |||
591 | std::lock_guard<std::recursive_mutex> guard( | |||
592 | GetObjectFile()->GetModule()->GetMutex()); | |||
593 | ||||
594 | auto type_system_or_err = | |||
595 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
596 | if (auto err = type_system_or_err.takeError()) { | |||
597 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get dynamic array info for UID"); } else ::llvm::consumeError(::std::move(error_private)); } while (0 ) | |||
598 | std::move(err), "Unable to get dynamic array info for UID")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get dynamic array info for UID"); } else ::llvm::consumeError(::std::move(error_private)); } while (0 ); | |||
599 | return false; | |||
600 | } | |||
601 | ||||
602 | TypeSystemClang *clang_ast_ctx = | |||
603 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
604 | ||||
605 | if (!clang_ast_ctx) | |||
606 | return false; | |||
607 | ||||
608 | PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); | |||
609 | if (!pdb) | |||
610 | return false; | |||
611 | ||||
612 | return pdb->CompleteTypeFromPDB(compiler_type); | |||
613 | } | |||
614 | ||||
615 | lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { | |||
616 | auto type_system_or_err = | |||
617 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
618 | if (auto err = type_system_or_err.takeError()) { | |||
619 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get decl for UID"); } else ::llvm::consumeError (::std::move(error_private)); } while (0) | |||
620 | std::move(err), "Unable to get decl for UID")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get decl for UID"); } else ::llvm::consumeError (::std::move(error_private)); } while (0); | |||
621 | return CompilerDecl(); | |||
622 | } | |||
623 | ||||
624 | TypeSystemClang *clang_ast_ctx = | |||
625 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
626 | if (!clang_ast_ctx) | |||
627 | return CompilerDecl(); | |||
628 | ||||
629 | PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); | |||
630 | if (!pdb) | |||
631 | return CompilerDecl(); | |||
632 | ||||
633 | auto symbol = m_session_up->getSymbolById(uid); | |||
634 | if (!symbol) | |||
635 | return CompilerDecl(); | |||
636 | ||||
637 | auto decl = pdb->GetDeclForSymbol(*symbol); | |||
638 | if (!decl) | |||
639 | return CompilerDecl(); | |||
640 | ||||
641 | return clang_ast_ctx->GetCompilerDecl(decl); | |||
642 | } | |||
643 | ||||
644 | lldb_private::CompilerDeclContext | |||
645 | SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { | |||
646 | auto type_system_or_err = | |||
647 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
648 | if (auto err = type_system_or_err.takeError()) { | |||
649 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get DeclContext for UID"); } else ::llvm ::consumeError(::std::move(error_private)); } while (0) | |||
650 | std::move(err), "Unable to get DeclContext for UID")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get DeclContext for UID"); } else ::llvm ::consumeError(::std::move(error_private)); } while (0); | |||
651 | return CompilerDeclContext(); | |||
652 | } | |||
653 | ||||
654 | TypeSystemClang *clang_ast_ctx = | |||
655 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
656 | if (!clang_ast_ctx) | |||
657 | return CompilerDeclContext(); | |||
658 | ||||
659 | PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); | |||
660 | if (!pdb) | |||
661 | return CompilerDeclContext(); | |||
662 | ||||
663 | auto symbol = m_session_up->getSymbolById(uid); | |||
664 | if (!symbol) | |||
665 | return CompilerDeclContext(); | |||
666 | ||||
667 | auto decl_context = pdb->GetDeclContextForSymbol(*symbol); | |||
668 | if (!decl_context) | |||
669 | return GetDeclContextContainingUID(uid); | |||
670 | ||||
671 | return clang_ast_ctx->CreateDeclContext(decl_context); | |||
672 | } | |||
673 | ||||
674 | lldb_private::CompilerDeclContext | |||
675 | SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { | |||
676 | auto type_system_or_err = | |||
677 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
678 | if (auto err = type_system_or_err.takeError()) { | |||
679 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get DeclContext containing UID"); } else ::llvm::consumeError(::std::move(error_private)); } while (0 ) | |||
680 | std::move(err), "Unable to get DeclContext containing UID")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get DeclContext containing UID"); } else ::llvm::consumeError(::std::move(error_private)); } while (0 ); | |||
681 | return CompilerDeclContext(); | |||
682 | } | |||
683 | ||||
684 | TypeSystemClang *clang_ast_ctx = | |||
685 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
686 | if (!clang_ast_ctx) | |||
687 | return CompilerDeclContext(); | |||
688 | ||||
689 | PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); | |||
690 | if (!pdb) | |||
691 | return CompilerDeclContext(); | |||
692 | ||||
693 | auto symbol = m_session_up->getSymbolById(uid); | |||
694 | if (!symbol) | |||
695 | return CompilerDeclContext(); | |||
696 | ||||
697 | auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol); | |||
698 | assert(decl_context)((void)0); | |||
699 | ||||
700 | return clang_ast_ctx->CreateDeclContext(decl_context); | |||
701 | } | |||
702 | ||||
703 | void SymbolFilePDB::ParseDeclsForContext( | |||
704 | lldb_private::CompilerDeclContext decl_ctx) { | |||
705 | auto type_system_or_err = | |||
706 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
707 | if (auto err = type_system_or_err.takeError()) { | |||
708 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to parse decls for context"); } else ::llvm ::consumeError(::std::move(error_private)); } while (0) | |||
709 | std::move(err), "Unable to parse decls for context")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to parse decls for context"); } else ::llvm ::consumeError(::std::move(error_private)); } while (0); | |||
710 | return; | |||
711 | } | |||
712 | ||||
713 | TypeSystemClang *clang_ast_ctx = | |||
714 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
715 | if (!clang_ast_ctx) | |||
716 | return; | |||
717 | ||||
718 | PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); | |||
719 | if (!pdb) | |||
720 | return; | |||
721 | ||||
722 | pdb->ParseDeclsForDeclContext( | |||
723 | static_cast<clang::DeclContext *>(decl_ctx.GetOpaqueDeclContext())); | |||
724 | } | |||
725 | ||||
726 | uint32_t | |||
727 | SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, | |||
728 | SymbolContextItem resolve_scope, | |||
729 | lldb_private::SymbolContext &sc) { | |||
730 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
731 | uint32_t resolved_flags = 0; | |||
732 | if (resolve_scope & eSymbolContextCompUnit || | |||
733 | resolve_scope & eSymbolContextVariable || | |||
734 | resolve_scope & eSymbolContextFunction || | |||
735 | resolve_scope & eSymbolContextBlock || | |||
736 | resolve_scope & eSymbolContextLineEntry) { | |||
737 | auto cu_sp = GetCompileUnitContainsAddress(so_addr); | |||
738 | if (!cu_sp) { | |||
739 | if (resolved_flags & eSymbolContextVariable) { | |||
740 | // TODO: Resolve variables | |||
741 | } | |||
742 | return 0; | |||
743 | } | |||
744 | sc.comp_unit = cu_sp.get(); | |||
745 | resolved_flags |= eSymbolContextCompUnit; | |||
746 | lldbassert(sc.module_sp == cu_sp->GetModule())lldb_private::lldb_assert(static_cast<bool>(sc.module_sp == cu_sp->GetModule()), "sc.module_sp == cu_sp->GetModule()" , __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 746); | |||
747 | } | |||
748 | ||||
749 | if (resolve_scope & eSymbolContextFunction || | |||
750 | resolve_scope & eSymbolContextBlock) { | |||
751 | addr_t file_vm_addr = so_addr.GetFileAddress(); | |||
752 | auto symbol_up = | |||
753 | m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function); | |||
754 | if (symbol_up) { | |||
755 | auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); | |||
756 | assert(pdb_func)((void)0); | |||
757 | auto func_uid = pdb_func->getSymIndexId(); | |||
758 | sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); | |||
759 | if (sc.function == nullptr) | |||
760 | sc.function = | |||
761 | ParseCompileUnitFunctionForPDBFunc(*pdb_func, *sc.comp_unit); | |||
762 | if (sc.function) { | |||
763 | resolved_flags |= eSymbolContextFunction; | |||
764 | if (resolve_scope & eSymbolContextBlock) { | |||
765 | auto block_symbol = m_session_up->findSymbolByAddress( | |||
766 | file_vm_addr, PDB_SymType::Block); | |||
767 | auto block_id = block_symbol ? block_symbol->getSymIndexId() | |||
768 | : sc.function->GetID(); | |||
769 | sc.block = sc.function->GetBlock(true).FindBlockByID(block_id); | |||
770 | if (sc.block) | |||
771 | resolved_flags |= eSymbolContextBlock; | |||
772 | } | |||
773 | } | |||
774 | } | |||
775 | } | |||
776 | ||||
777 | if (resolve_scope & eSymbolContextLineEntry) { | |||
778 | if (auto *line_table = sc.comp_unit->GetLineTable()) { | |||
779 | Address addr(so_addr); | |||
780 | if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) | |||
781 | resolved_flags |= eSymbolContextLineEntry; | |||
782 | } | |||
783 | } | |||
784 | ||||
785 | return resolved_flags; | |||
786 | } | |||
787 | ||||
788 | uint32_t SymbolFilePDB::ResolveSymbolContext( | |||
789 | const lldb_private::SourceLocationSpec &src_location_spec, | |||
790 | SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) { | |||
791 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
792 | const size_t old_size = sc_list.GetSize(); | |||
793 | const FileSpec &file_spec = src_location_spec.GetFileSpec(); | |||
794 | const uint32_t line = src_location_spec.GetLine().getValueOr(0); | |||
795 | if (resolve_scope & lldb::eSymbolContextCompUnit) { | |||
796 | // Locate all compilation units with line numbers referencing the specified | |||
797 | // file. For example, if `file_spec` is <vector>, then this should return | |||
798 | // all source files and header files that reference <vector>, either | |||
799 | // directly or indirectly. | |||
800 | auto compilands = m_session_up->findCompilandsForSourceFile( | |||
801 | file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive); | |||
802 | ||||
803 | if (!compilands) | |||
804 | return 0; | |||
805 | ||||
806 | // For each one, either find its previously parsed data or parse it afresh | |||
807 | // and add it to the symbol context list. | |||
808 | while (auto compiland = compilands->getNext()) { | |||
809 | // If we're not checking inlines, then don't add line information for | |||
810 | // this file unless the FileSpec matches. For inline functions, we don't | |||
811 | // have to match the FileSpec since they could be defined in headers | |||
812 | // other than file specified in FileSpec. | |||
813 | if (!src_location_spec.GetCheckInlines()) { | |||
814 | std::string source_file = compiland->getSourceFileFullPath(); | |||
815 | if (source_file.empty()) | |||
816 | continue; | |||
817 | FileSpec this_spec(source_file, FileSpec::Style::windows); | |||
818 | bool need_full_match = !file_spec.GetDirectory().IsEmpty(); | |||
819 | if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0) | |||
820 | continue; | |||
821 | } | |||
822 | ||||
823 | SymbolContext sc; | |||
824 | auto cu = ParseCompileUnitForUID(compiland->getSymIndexId()); | |||
825 | if (!cu) | |||
826 | continue; | |||
827 | sc.comp_unit = cu.get(); | |||
828 | sc.module_sp = cu->GetModule(); | |||
829 | ||||
830 | // If we were asked to resolve line entries, add all entries to the line | |||
831 | // table that match the requested line (or all lines if `line` == 0). | |||
832 | if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock | | |||
833 | eSymbolContextLineEntry)) { | |||
834 | bool has_line_table = ParseCompileUnitLineTable(*sc.comp_unit, line); | |||
835 | ||||
836 | if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) { | |||
837 | // The query asks for line entries, but we can't get them for the | |||
838 | // compile unit. This is not normal for `line` = 0. So just assert | |||
839 | // it. | |||
840 | assert(line && "Couldn't get all line entries!\n")((void)0); | |||
841 | ||||
842 | // Current compiland does not have the requested line. Search next. | |||
843 | continue; | |||
844 | } | |||
845 | ||||
846 | if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) { | |||
847 | if (!has_line_table) | |||
848 | continue; | |||
849 | ||||
850 | auto *line_table = sc.comp_unit->GetLineTable(); | |||
851 | lldbassert(line_table)lldb_private::lldb_assert(static_cast<bool>(line_table) , "line_table", __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 851); | |||
852 | ||||
853 | uint32_t num_line_entries = line_table->GetSize(); | |||
854 | // Skip the terminal line entry. | |||
855 | --num_line_entries; | |||
856 | ||||
857 | // If `line `!= 0, see if we can resolve function for each line entry | |||
858 | // in the line table. | |||
859 | for (uint32_t line_idx = 0; line && line_idx < num_line_entries; | |||
860 | ++line_idx) { | |||
861 | if (!line_table->GetLineEntryAtIndex(line_idx, sc.line_entry)) | |||
862 | continue; | |||
863 | ||||
864 | auto file_vm_addr = | |||
865 | sc.line_entry.range.GetBaseAddress().GetFileAddress(); | |||
866 | if (file_vm_addr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL || file_vm_addr == 0) | |||
867 | continue; | |||
868 | ||||
869 | auto symbol_up = m_session_up->findSymbolByAddress( | |||
870 | file_vm_addr, PDB_SymType::Function); | |||
871 | if (symbol_up) { | |||
872 | auto func_uid = symbol_up->getSymIndexId(); | |||
873 | sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); | |||
874 | if (sc.function == nullptr) { | |||
875 | auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); | |||
876 | assert(pdb_func)((void)0); | |||
877 | sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, | |||
878 | *sc.comp_unit); | |||
879 | } | |||
880 | if (sc.function && (resolve_scope & eSymbolContextBlock)) { | |||
881 | Block &block = sc.function->GetBlock(true); | |||
882 | sc.block = block.FindBlockByID(sc.function->GetID()); | |||
883 | } | |||
884 | } | |||
885 | sc_list.Append(sc); | |||
886 | } | |||
887 | } else if (has_line_table) { | |||
888 | // We can parse line table for the compile unit. But no query to | |||
889 | // resolve function or block. We append `sc` to the list anyway. | |||
890 | sc_list.Append(sc); | |||
891 | } | |||
892 | } else { | |||
893 | // No query for line entry, function or block. But we have a valid | |||
894 | // compile unit, append `sc` to the list. | |||
895 | sc_list.Append(sc); | |||
896 | } | |||
897 | } | |||
898 | } | |||
899 | return sc_list.GetSize() - old_size; | |||
900 | } | |||
901 | ||||
902 | std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) { | |||
903 | // Cache public names at first | |||
904 | if (m_public_names.empty()) | |||
905 | if (auto result_up = | |||
906 | m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol)) | |||
907 | while (auto symbol_up = result_up->getNext()) | |||
908 | if (auto addr = symbol_up->getRawSymbol().getVirtualAddress()) | |||
909 | m_public_names[addr] = symbol_up->getRawSymbol().getName(); | |||
910 | ||||
911 | // Look up the name in the cache | |||
912 | return m_public_names.lookup(pdb_data.getVirtualAddress()); | |||
913 | } | |||
914 | ||||
915 | VariableSP SymbolFilePDB::ParseVariableForPDBData( | |||
916 | const lldb_private::SymbolContext &sc, | |||
917 | const llvm::pdb::PDBSymbolData &pdb_data) { | |||
918 | VariableSP var_sp; | |||
919 | uint32_t var_uid = pdb_data.getSymIndexId(); | |||
920 | auto result = m_variables.find(var_uid); | |||
921 | if (result != m_variables.end()) | |||
922 | return result->second; | |||
923 | ||||
924 | ValueType scope = eValueTypeInvalid; | |||
925 | bool is_static_member = false; | |||
926 | bool is_external = false; | |||
927 | bool is_artificial = false; | |||
928 | ||||
929 | switch (pdb_data.getDataKind()) { | |||
930 | case PDB_DataKind::Global: | |||
931 | scope = eValueTypeVariableGlobal; | |||
932 | is_external = true; | |||
933 | break; | |||
934 | case PDB_DataKind::Local: | |||
935 | scope = eValueTypeVariableLocal; | |||
936 | break; | |||
937 | case PDB_DataKind::FileStatic: | |||
938 | scope = eValueTypeVariableStatic; | |||
939 | break; | |||
940 | case PDB_DataKind::StaticMember: | |||
941 | is_static_member = true; | |||
942 | scope = eValueTypeVariableStatic; | |||
943 | break; | |||
944 | case PDB_DataKind::Member: | |||
945 | scope = eValueTypeVariableStatic; | |||
946 | break; | |||
947 | case PDB_DataKind::Param: | |||
948 | scope = eValueTypeVariableArgument; | |||
949 | break; | |||
950 | case PDB_DataKind::Constant: | |||
951 | scope = eValueTypeConstResult; | |||
952 | break; | |||
953 | default: | |||
954 | break; | |||
955 | } | |||
956 | ||||
957 | switch (pdb_data.getLocationType()) { | |||
958 | case PDB_LocType::TLS: | |||
959 | scope = eValueTypeVariableThreadLocal; | |||
960 | break; | |||
961 | case PDB_LocType::RegRel: { | |||
962 | // It is a `this` pointer. | |||
963 | if (pdb_data.getDataKind() == PDB_DataKind::ObjectPtr) { | |||
964 | scope = eValueTypeVariableArgument; | |||
965 | is_artificial = true; | |||
966 | } | |||
967 | } break; | |||
968 | default: | |||
969 | break; | |||
970 | } | |||
971 | ||||
972 | Declaration decl; | |||
973 | if (!is_artificial && !pdb_data.isCompilerGenerated()) { | |||
974 | if (auto lines = pdb_data.getLineNumbers()) { | |||
975 | if (auto first_line = lines->getNext()) { | |||
976 | uint32_t src_file_id = first_line->getSourceFileId(); | |||
977 | auto src_file = m_session_up->getSourceFileById(src_file_id); | |||
978 | if (src_file) { | |||
979 | FileSpec spec(src_file->getFileName()); | |||
980 | decl.SetFile(spec); | |||
981 | decl.SetColumn(first_line->getColumnNumber()); | |||
982 | decl.SetLine(first_line->getLineNumber()); | |||
983 | } | |||
984 | } | |||
985 | } | |||
986 | } | |||
987 | ||||
988 | Variable::RangeList ranges; | |||
989 | SymbolContextScope *context_scope = sc.comp_unit; | |||
990 | if (scope == eValueTypeVariableLocal || scope == eValueTypeVariableArgument) { | |||
991 | if (sc.function) { | |||
992 | Block &function_block = sc.function->GetBlock(true); | |||
993 | Block *block = | |||
994 | function_block.FindBlockByID(pdb_data.getLexicalParentId()); | |||
995 | if (!block) | |||
996 | block = &function_block; | |||
997 | ||||
998 | context_scope = block; | |||
999 | ||||
1000 | for (size_t i = 0, num_ranges = block->GetNumRanges(); i < num_ranges; | |||
1001 | ++i) { | |||
1002 | AddressRange range; | |||
1003 | if (!block->GetRangeAtIndex(i, range)) | |||
1004 | continue; | |||
1005 | ||||
1006 | ranges.Append(range.GetBaseAddress().GetFileAddress(), | |||
1007 | range.GetByteSize()); | |||
1008 | } | |||
1009 | } | |||
1010 | } | |||
1011 | ||||
1012 | SymbolFileTypeSP type_sp = | |||
1013 | std::make_shared<SymbolFileType>(*this, pdb_data.getTypeId()); | |||
1014 | ||||
1015 | auto var_name = pdb_data.getName(); | |||
1016 | auto mangled = GetMangledForPDBData(pdb_data); | |||
1017 | auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str(); | |||
1018 | ||||
1019 | bool is_constant; | |||
1020 | DWARFExpression location = ConvertPDBLocationToDWARFExpression( | |||
1021 | GetObjectFile()->GetModule(), pdb_data, ranges, is_constant); | |||
1022 | ||||
1023 | var_sp = std::make_shared<Variable>( | |||
1024 | var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope, | |||
1025 | ranges, &decl, location, is_external, is_artificial, is_constant, | |||
1026 | is_static_member); | |||
1027 | ||||
1028 | m_variables.insert(std::make_pair(var_uid, var_sp)); | |||
1029 | return var_sp; | |||
1030 | } | |||
1031 | ||||
1032 | size_t | |||
1033 | SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc, | |||
1034 | const llvm::pdb::PDBSymbol &pdb_symbol, | |||
1035 | lldb_private::VariableList *variable_list) { | |||
1036 | size_t num_added = 0; | |||
1037 | ||||
1038 | if (auto pdb_data = llvm::dyn_cast<PDBSymbolData>(&pdb_symbol)) { | |||
1039 | VariableListSP local_variable_list_sp; | |||
1040 | ||||
1041 | auto result = m_variables.find(pdb_data->getSymIndexId()); | |||
1042 | if (result != m_variables.end()) { | |||
1043 | if (variable_list) | |||
1044 | variable_list->AddVariableIfUnique(result->second); | |||
1045 | } else { | |||
1046 | // Prepare right VariableList for this variable. | |||
1047 | if (auto lexical_parent = pdb_data->getLexicalParent()) { | |||
1048 | switch (lexical_parent->getSymTag()) { | |||
1049 | case PDB_SymType::Exe: | |||
1050 | assert(sc.comp_unit)((void)0); | |||
1051 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | |||
1052 | case PDB_SymType::Compiland: { | |||
1053 | if (sc.comp_unit) { | |||
1054 | local_variable_list_sp = sc.comp_unit->GetVariableList(false); | |||
1055 | if (!local_variable_list_sp) { | |||
1056 | local_variable_list_sp = std::make_shared<VariableList>(); | |||
1057 | sc.comp_unit->SetVariableList(local_variable_list_sp); | |||
1058 | } | |||
1059 | } | |||
1060 | } break; | |||
1061 | case PDB_SymType::Block: | |||
1062 | case PDB_SymType::Function: { | |||
1063 | if (sc.function) { | |||
1064 | Block *block = sc.function->GetBlock(true).FindBlockByID( | |||
1065 | lexical_parent->getSymIndexId()); | |||
1066 | if (block) { | |||
1067 | local_variable_list_sp = block->GetBlockVariableList(false); | |||
1068 | if (!local_variable_list_sp) { | |||
1069 | local_variable_list_sp = std::make_shared<VariableList>(); | |||
1070 | block->SetVariableList(local_variable_list_sp); | |||
1071 | } | |||
1072 | } | |||
1073 | } | |||
1074 | } break; | |||
1075 | default: | |||
1076 | break; | |||
1077 | } | |||
1078 | } | |||
1079 | ||||
1080 | if (local_variable_list_sp) { | |||
1081 | if (auto var_sp = ParseVariableForPDBData(sc, *pdb_data)) { | |||
1082 | local_variable_list_sp->AddVariableIfUnique(var_sp); | |||
1083 | if (variable_list) | |||
1084 | variable_list->AddVariableIfUnique(var_sp); | |||
1085 | ++num_added; | |||
1086 | PDBASTParser *ast = GetPDBAstParser(); | |||
1087 | if (ast) | |||
1088 | ast->GetDeclForSymbol(*pdb_data); | |||
1089 | } | |||
1090 | } | |||
1091 | } | |||
1092 | } | |||
1093 | ||||
1094 | if (auto results = pdb_symbol.findAllChildren()) { | |||
1095 | while (auto result = results->getNext()) | |||
1096 | num_added += ParseVariables(sc, *result, variable_list); | |||
1097 | } | |||
1098 | ||||
1099 | return num_added; | |||
1100 | } | |||
1101 | ||||
1102 | void SymbolFilePDB::FindGlobalVariables( | |||
1103 | lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx, | |||
1104 | uint32_t max_matches, lldb_private::VariableList &variables) { | |||
1105 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
1106 | if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) | |||
| ||||
1107 | return; | |||
1108 | if (name.IsEmpty()) | |||
1109 | return; | |||
1110 | ||||
1111 | auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); | |||
1112 | if (!results) | |||
1113 | return; | |||
1114 | ||||
1115 | uint32_t matches = 0; | |||
1116 | size_t old_size = variables.GetSize(); | |||
1117 | while (auto result = results->getNext()) { | |||
1118 | auto pdb_data = llvm::dyn_cast<PDBSymbolData>(result.get()); | |||
1119 | if (max_matches > 0 && matches >= max_matches) | |||
1120 | break; | |||
1121 | ||||
1122 | SymbolContext sc; | |||
1123 | sc.module_sp = m_objfile_sp->GetModule(); | |||
1124 | lldbassert(sc.module_sp.get())lldb_private::lldb_assert(static_cast<bool>(sc.module_sp .get()), "sc.module_sp.get()", __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 1124); | |||
1125 | ||||
1126 | if (!name.GetStringRef().equals( | |||
1127 | MSVCUndecoratedNameParser::DropScope(pdb_data->getName()))) | |||
| ||||
1128 | continue; | |||
1129 | ||||
1130 | sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get(); | |||
1131 | // FIXME: We are not able to determine the compile unit. | |||
1132 | if (sc.comp_unit == nullptr) | |||
1133 | continue; | |||
1134 | ||||
1135 | if (parent_decl_ctx.IsValid() && | |||
1136 | GetDeclContextContainingUID(result->getSymIndexId()) != parent_decl_ctx) | |||
1137 | continue; | |||
1138 | ||||
1139 | ParseVariables(sc, *pdb_data, &variables); | |||
1140 | matches = variables.GetSize() - old_size; | |||
1141 | } | |||
1142 | } | |||
1143 | ||||
1144 | void SymbolFilePDB::FindGlobalVariables( | |||
1145 | const lldb_private::RegularExpression ®ex, uint32_t max_matches, | |||
1146 | lldb_private::VariableList &variables) { | |||
1147 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
1148 | if (!regex.IsValid()) | |||
1149 | return; | |||
1150 | auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); | |||
1151 | if (!results) | |||
1152 | return; | |||
1153 | ||||
1154 | uint32_t matches = 0; | |||
1155 | size_t old_size = variables.GetSize(); | |||
1156 | while (auto pdb_data = results->getNext()) { | |||
1157 | if (max_matches > 0 && matches >= max_matches) | |||
1158 | break; | |||
1159 | ||||
1160 | auto var_name = pdb_data->getName(); | |||
1161 | if (var_name.empty()) | |||
1162 | continue; | |||
1163 | if (!regex.Execute(var_name)) | |||
1164 | continue; | |||
1165 | SymbolContext sc; | |||
1166 | sc.module_sp = m_objfile_sp->GetModule(); | |||
1167 | lldbassert(sc.module_sp.get())lldb_private::lldb_assert(static_cast<bool>(sc.module_sp .get()), "sc.module_sp.get()", __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 1167); | |||
1168 | ||||
1169 | sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get(); | |||
1170 | // FIXME: We are not able to determine the compile unit. | |||
1171 | if (sc.comp_unit == nullptr) | |||
1172 | continue; | |||
1173 | ||||
1174 | ParseVariables(sc, *pdb_data, &variables); | |||
1175 | matches = variables.GetSize() - old_size; | |||
1176 | } | |||
1177 | } | |||
1178 | ||||
1179 | bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func, | |||
1180 | bool include_inlines, | |||
1181 | lldb_private::SymbolContextList &sc_list) { | |||
1182 | lldb_private::SymbolContext sc; | |||
1183 | sc.comp_unit = ParseCompileUnitForUID(pdb_func.getCompilandId()).get(); | |||
1184 | if (!sc.comp_unit) | |||
1185 | return false; | |||
1186 | sc.module_sp = sc.comp_unit->GetModule(); | |||
1187 | sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, *sc.comp_unit); | |||
1188 | if (!sc.function) | |||
1189 | return false; | |||
1190 | ||||
1191 | sc_list.Append(sc); | |||
1192 | return true; | |||
1193 | } | |||
1194 | ||||
1195 | bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines, | |||
1196 | lldb_private::SymbolContextList &sc_list) { | |||
1197 | auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); | |||
1198 | if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute())) | |||
1199 | return false; | |||
1200 | return ResolveFunction(*pdb_func_up, include_inlines, sc_list); | |||
1201 | } | |||
1202 | ||||
1203 | void SymbolFilePDB::CacheFunctionNames() { | |||
1204 | if (!m_func_full_names.IsEmpty()) | |||
1205 | return; | |||
1206 | ||||
1207 | std::map<uint64_t, uint32_t> addr_ids; | |||
1208 | ||||
1209 | if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) { | |||
1210 | while (auto pdb_func_up = results_up->getNext()) { | |||
1211 | if (pdb_func_up->isCompilerGenerated()) | |||
1212 | continue; | |||
1213 | ||||
1214 | auto name = pdb_func_up->getName(); | |||
1215 | auto demangled_name = pdb_func_up->getUndecoratedName(); | |||
1216 | if (name.empty() && demangled_name.empty()) | |||
1217 | continue; | |||
1218 | ||||
1219 | auto uid = pdb_func_up->getSymIndexId(); | |||
1220 | if (!demangled_name.empty() && pdb_func_up->getVirtualAddress()) | |||
1221 | addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid)); | |||
1222 | ||||
1223 | if (auto parent = pdb_func_up->getClassParent()) { | |||
1224 | ||||
1225 | // PDB have symbols for class/struct methods or static methods in Enum | |||
1226 | // Class. We won't bother to check if the parent is UDT or Enum here. | |||
1227 | m_func_method_names.Append(ConstString(name), uid); | |||
1228 | ||||
1229 | // To search a method name, like NS::Class:MemberFunc, LLDB searches | |||
1230 | // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does | |||
1231 | // not have information of this, we extract base names and cache them | |||
1232 | // by our own effort. | |||
1233 | llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name); | |||
1234 | if (!basename.empty()) | |||
1235 | m_func_base_names.Append(ConstString(basename), uid); | |||
1236 | else { | |||
1237 | m_func_base_names.Append(ConstString(name), uid); | |||
1238 | } | |||
1239 | ||||
1240 | if (!demangled_name.empty()) | |||
1241 | m_func_full_names.Append(ConstString(demangled_name), uid); | |||
1242 | ||||
1243 | } else { | |||
1244 | // Handle not-method symbols. | |||
1245 | ||||
1246 | // The function name might contain namespace, or its lexical scope. | |||
1247 | llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name); | |||
1248 | if (!basename.empty()) | |||
1249 | m_func_base_names.Append(ConstString(basename), uid); | |||
1250 | else | |||
1251 | m_func_base_names.Append(ConstString(name), uid); | |||
1252 | ||||
1253 | if (name == "main") { | |||
1254 | m_func_full_names.Append(ConstString(name), uid); | |||
1255 | ||||
1256 | if (!demangled_name.empty() && name != demangled_name) { | |||
1257 | m_func_full_names.Append(ConstString(demangled_name), uid); | |||
1258 | m_func_base_names.Append(ConstString(demangled_name), uid); | |||
1259 | } | |||
1260 | } else if (!demangled_name.empty()) { | |||
1261 | m_func_full_names.Append(ConstString(demangled_name), uid); | |||
1262 | } else { | |||
1263 | m_func_full_names.Append(ConstString(name), uid); | |||
1264 | } | |||
1265 | } | |||
1266 | } | |||
1267 | } | |||
1268 | ||||
1269 | if (auto results_up = | |||
1270 | m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) { | |||
1271 | while (auto pub_sym_up = results_up->getNext()) { | |||
1272 | if (!pub_sym_up->isFunction()) | |||
1273 | continue; | |||
1274 | auto name = pub_sym_up->getName(); | |||
1275 | if (name.empty()) | |||
1276 | continue; | |||
1277 | ||||
1278 | if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) { | |||
1279 | auto vm_addr = pub_sym_up->getVirtualAddress(); | |||
1280 | ||||
1281 | // PDB public symbol has mangled name for its associated function. | |||
1282 | if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) { | |||
1283 | // Cache mangled name. | |||
1284 | m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]); | |||
1285 | } | |||
1286 | } | |||
1287 | } | |||
1288 | } | |||
1289 | // Sort them before value searching is working properly | |||
1290 | m_func_full_names.Sort(); | |||
1291 | m_func_full_names.SizeToFit(); | |||
1292 | m_func_method_names.Sort(); | |||
1293 | m_func_method_names.SizeToFit(); | |||
1294 | m_func_base_names.Sort(); | |||
1295 | m_func_base_names.SizeToFit(); | |||
1296 | } | |||
1297 | ||||
1298 | void SymbolFilePDB::FindFunctions( | |||
1299 | lldb_private::ConstString name, | |||
1300 | const lldb_private::CompilerDeclContext &parent_decl_ctx, | |||
1301 | FunctionNameType name_type_mask, bool include_inlines, | |||
1302 | lldb_private::SymbolContextList &sc_list) { | |||
1303 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
1304 | lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0)lldb_private::lldb_assert(static_cast<bool>((name_type_mask & eFunctionNameTypeAuto) == 0), "(name_type_mask & eFunctionNameTypeAuto) == 0" , __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 1304); | |||
1305 | ||||
1306 | if (name_type_mask == eFunctionNameTypeNone) | |||
1307 | return; | |||
1308 | if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) | |||
1309 | return; | |||
1310 | if (name.IsEmpty()) | |||
1311 | return; | |||
1312 | ||||
1313 | if (name_type_mask & eFunctionNameTypeFull || | |||
1314 | name_type_mask & eFunctionNameTypeBase || | |||
1315 | name_type_mask & eFunctionNameTypeMethod) { | |||
1316 | CacheFunctionNames(); | |||
1317 | ||||
1318 | std::set<uint32_t> resolved_ids; | |||
1319 | auto ResolveFn = [this, &name, parent_decl_ctx, include_inlines, &sc_list, | |||
1320 | &resolved_ids](UniqueCStringMap<uint32_t> &Names) { | |||
1321 | std::vector<uint32_t> ids; | |||
1322 | if (!Names.GetValues(name, ids)) | |||
1323 | return; | |||
1324 | ||||
1325 | for (uint32_t id : ids) { | |||
1326 | if (resolved_ids.find(id) != resolved_ids.end()) | |||
1327 | continue; | |||
1328 | ||||
1329 | if (parent_decl_ctx.IsValid() && | |||
1330 | GetDeclContextContainingUID(id) != parent_decl_ctx) | |||
1331 | continue; | |||
1332 | ||||
1333 | if (ResolveFunction(id, include_inlines, sc_list)) | |||
1334 | resolved_ids.insert(id); | |||
1335 | } | |||
1336 | }; | |||
1337 | if (name_type_mask & eFunctionNameTypeFull) { | |||
1338 | ResolveFn(m_func_full_names); | |||
1339 | ResolveFn(m_func_base_names); | |||
1340 | ResolveFn(m_func_method_names); | |||
1341 | } | |||
1342 | if (name_type_mask & eFunctionNameTypeBase) | |||
1343 | ResolveFn(m_func_base_names); | |||
1344 | if (name_type_mask & eFunctionNameTypeMethod) | |||
1345 | ResolveFn(m_func_method_names); | |||
1346 | } | |||
1347 | } | |||
1348 | ||||
1349 | void SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, | |||
1350 | bool include_inlines, | |||
1351 | lldb_private::SymbolContextList &sc_list) { | |||
1352 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
1353 | if (!regex.IsValid()) | |||
1354 | return; | |||
1355 | ||||
1356 | CacheFunctionNames(); | |||
1357 | ||||
1358 | std::set<uint32_t> resolved_ids; | |||
1359 | auto ResolveFn = [®ex, include_inlines, &sc_list, &resolved_ids, | |||
1360 | this](UniqueCStringMap<uint32_t> &Names) { | |||
1361 | std::vector<uint32_t> ids; | |||
1362 | if (Names.GetValues(regex, ids)) { | |||
1363 | for (auto id : ids) { | |||
1364 | if (resolved_ids.find(id) == resolved_ids.end()) | |||
1365 | if (ResolveFunction(id, include_inlines, sc_list)) | |||
1366 | resolved_ids.insert(id); | |||
1367 | } | |||
1368 | } | |||
1369 | }; | |||
1370 | ResolveFn(m_func_full_names); | |||
1371 | ResolveFn(m_func_base_names); | |||
1372 | } | |||
1373 | ||||
1374 | void SymbolFilePDB::GetMangledNamesForFunction( | |||
1375 | const std::string &scope_qualified_name, | |||
1376 | std::vector<lldb_private::ConstString> &mangled_names) {} | |||
1377 | ||||
1378 | void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { | |||
1379 | std::set<lldb::addr_t> sym_addresses; | |||
1380 | for (size_t i = 0; i < symtab.GetNumSymbols(); i++) | |||
1381 | sym_addresses.insert(symtab.SymbolAtIndex(i)->GetFileAddress()); | |||
1382 | ||||
1383 | auto results = m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>(); | |||
1384 | if (!results) | |||
1385 | return; | |||
1386 | ||||
1387 | auto section_list = m_objfile_sp->GetSectionList(); | |||
1388 | if (!section_list) | |||
1389 | return; | |||
1390 | ||||
1391 | while (auto pub_symbol = results->getNext()) { | |||
1392 | auto section_id = pub_symbol->getAddressSection(); | |||
1393 | ||||
1394 | auto section = section_list->FindSectionByID(section_id); | |||
1395 | if (!section) | |||
1396 | continue; | |||
1397 | ||||
1398 | auto offset = pub_symbol->getAddressOffset(); | |||
1399 | ||||
1400 | auto file_addr = section->GetFileAddress() + offset; | |||
1401 | if (sym_addresses.find(file_addr) != sym_addresses.end()) | |||
1402 | continue; | |||
1403 | sym_addresses.insert(file_addr); | |||
1404 | ||||
1405 | auto size = pub_symbol->getLength(); | |||
1406 | symtab.AddSymbol( | |||
1407 | Symbol(pub_symbol->getSymIndexId(), // symID | |||
1408 | pub_symbol->getName().c_str(), // name | |||
1409 | pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type | |||
1410 | true, // external | |||
1411 | false, // is_debug | |||
1412 | false, // is_trampoline | |||
1413 | false, // is_artificial | |||
1414 | section, // section_sp | |||
1415 | offset, // value | |||
1416 | size, // size | |||
1417 | size != 0, // size_is_valid | |||
1418 | false, // contains_linker_annotations | |||
1419 | 0 // flags | |||
1420 | )); | |||
1421 | } | |||
1422 | ||||
1423 | symtab.CalculateSymbolSizes(); | |||
1424 | symtab.Finalize(); | |||
1425 | } | |||
1426 | ||||
1427 | void SymbolFilePDB::FindTypes( | |||
1428 | lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx, | |||
1429 | uint32_t max_matches, | |||
1430 | llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, | |||
1431 | lldb_private::TypeMap &types) { | |||
1432 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
1433 | if (!name) | |||
1434 | return; | |||
1435 | if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) | |||
1436 | return; | |||
1437 | ||||
1438 | searched_symbol_files.clear(); | |||
1439 | searched_symbol_files.insert(this); | |||
1440 | ||||
1441 | // There is an assumption 'name' is not a regex | |||
1442 | FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types); | |||
1443 | } | |||
1444 | ||||
1445 | void SymbolFilePDB::DumpClangAST(Stream &s) { | |||
1446 | auto type_system_or_err = | |||
1447 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
1448 | if (auto err = type_system_or_err.takeError()) { | |||
1449 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to dump ClangAST"); } else ::llvm::consumeError (::std::move(error_private)); } while (0) | |||
1450 | std::move(err), "Unable to dump ClangAST")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to dump ClangAST"); } else ::llvm::consumeError (::std::move(error_private)); } while (0); | |||
1451 | return; | |||
1452 | } | |||
1453 | ||||
1454 | auto *clang_type_system = | |||
1455 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
1456 | if (!clang_type_system) | |||
1457 | return; | |||
1458 | clang_type_system->Dump(s); | |||
1459 | } | |||
1460 | ||||
1461 | void SymbolFilePDB::FindTypesByRegex( | |||
1462 | const lldb_private::RegularExpression ®ex, uint32_t max_matches, | |||
1463 | lldb_private::TypeMap &types) { | |||
1464 | // When searching by regex, we need to go out of our way to limit the search | |||
1465 | // space as much as possible since this searches EVERYTHING in the PDB, | |||
1466 | // manually doing regex comparisons. PDB library isn't optimized for regex | |||
1467 | // searches or searches across multiple symbol types at the same time, so the | |||
1468 | // best we can do is to search enums, then typedefs, then classes one by one, | |||
1469 | // and do a regex comparison against each of them. | |||
1470 | PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef, | |||
1471 | PDB_SymType::UDT}; | |||
1472 | std::unique_ptr<IPDBEnumSymbols> results; | |||
1473 | ||||
1474 | uint32_t matches = 0; | |||
1475 | ||||
1476 | for (auto tag : tags_to_search) { | |||
1477 | results = m_global_scope_up->findAllChildren(tag); | |||
1478 | if (!results) | |||
1479 | continue; | |||
1480 | ||||
1481 | while (auto result = results->getNext()) { | |||
1482 | if (max_matches > 0 && matches >= max_matches) | |||
1483 | break; | |||
1484 | ||||
1485 | std::string type_name; | |||
1486 | if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get())) | |||
1487 | type_name = enum_type->getName(); | |||
1488 | else if (auto typedef_type = | |||
1489 | llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get())) | |||
1490 | type_name = typedef_type->getName(); | |||
1491 | else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get())) | |||
1492 | type_name = class_type->getName(); | |||
1493 | else { | |||
1494 | // We're looking only for types that have names. Skip symbols, as well | |||
1495 | // as unnamed types such as arrays, pointers, etc. | |||
1496 | continue; | |||
1497 | } | |||
1498 | ||||
1499 | if (!regex.Execute(type_name)) | |||
1500 | continue; | |||
1501 | ||||
1502 | // This should cause the type to get cached and stored in the `m_types` | |||
1503 | // lookup. | |||
1504 | if (!ResolveTypeUID(result->getSymIndexId())) | |||
1505 | continue; | |||
1506 | ||||
1507 | auto iter = m_types.find(result->getSymIndexId()); | |||
1508 | if (iter == m_types.end()) | |||
1509 | continue; | |||
1510 | types.Insert(iter->second); | |||
1511 | ++matches; | |||
1512 | } | |||
1513 | } | |||
1514 | } | |||
1515 | ||||
1516 | void SymbolFilePDB::FindTypesByName( | |||
1517 | llvm::StringRef name, | |||
1518 | const lldb_private::CompilerDeclContext &parent_decl_ctx, | |||
1519 | uint32_t max_matches, lldb_private::TypeMap &types) { | |||
1520 | std::unique_ptr<IPDBEnumSymbols> results; | |||
1521 | if (name.empty()) | |||
1522 | return; | |||
1523 | results = m_global_scope_up->findAllChildren(PDB_SymType::None); | |||
1524 | if (!results) | |||
1525 | return; | |||
1526 | ||||
1527 | uint32_t matches = 0; | |||
1528 | ||||
1529 | while (auto result = results->getNext()) { | |||
1530 | if (max_matches > 0 && matches >= max_matches) | |||
1531 | break; | |||
1532 | ||||
1533 | if (MSVCUndecoratedNameParser::DropScope( | |||
1534 | result->getRawSymbol().getName()) != name) | |||
1535 | continue; | |||
1536 | ||||
1537 | switch (result->getSymTag()) { | |||
1538 | case PDB_SymType::Enum: | |||
1539 | case PDB_SymType::UDT: | |||
1540 | case PDB_SymType::Typedef: | |||
1541 | break; | |||
1542 | default: | |||
1543 | // We're looking only for types that have names. Skip symbols, as well | |||
1544 | // as unnamed types such as arrays, pointers, etc. | |||
1545 | continue; | |||
1546 | } | |||
1547 | ||||
1548 | // This should cause the type to get cached and stored in the `m_types` | |||
1549 | // lookup. | |||
1550 | if (!ResolveTypeUID(result->getSymIndexId())) | |||
1551 | continue; | |||
1552 | ||||
1553 | if (parent_decl_ctx.IsValid() && | |||
1554 | GetDeclContextContainingUID(result->getSymIndexId()) != parent_decl_ctx) | |||
1555 | continue; | |||
1556 | ||||
1557 | auto iter = m_types.find(result->getSymIndexId()); | |||
1558 | if (iter == m_types.end()) | |||
1559 | continue; | |||
1560 | types.Insert(iter->second); | |||
1561 | ++matches; | |||
1562 | } | |||
1563 | } | |||
1564 | ||||
1565 | void SymbolFilePDB::FindTypes( | |||
1566 | llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, | |||
1567 | llvm::DenseSet<SymbolFile *> &searched_symbol_files, | |||
1568 | lldb_private::TypeMap &types) {} | |||
1569 | ||||
1570 | void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, | |||
1571 | uint32_t type_mask, | |||
1572 | TypeCollection &type_collection) { | |||
1573 | bool can_parse = false; | |||
1574 | switch (pdb_symbol.getSymTag()) { | |||
1575 | case PDB_SymType::ArrayType: | |||
1576 | can_parse = ((type_mask & eTypeClassArray) != 0); | |||
1577 | break; | |||
1578 | case PDB_SymType::BuiltinType: | |||
1579 | can_parse = ((type_mask & eTypeClassBuiltin) != 0); | |||
1580 | break; | |||
1581 | case PDB_SymType::Enum: | |||
1582 | can_parse = ((type_mask & eTypeClassEnumeration) != 0); | |||
1583 | break; | |||
1584 | case PDB_SymType::Function: | |||
1585 | case PDB_SymType::FunctionSig: | |||
1586 | can_parse = ((type_mask & eTypeClassFunction) != 0); | |||
1587 | break; | |||
1588 | case PDB_SymType::PointerType: | |||
1589 | can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer | | |||
1590 | eTypeClassMemberPointer)) != 0); | |||
1591 | break; | |||
1592 | case PDB_SymType::Typedef: | |||
1593 | can_parse = ((type_mask & eTypeClassTypedef) != 0); | |||
1594 | break; | |||
1595 | case PDB_SymType::UDT: { | |||
1596 | auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&pdb_symbol); | |||
1597 | assert(udt)((void)0); | |||
1598 | can_parse = (udt->getUdtKind() != PDB_UdtType::Interface && | |||
1599 | ((type_mask & (eTypeClassClass | eTypeClassStruct | | |||
1600 | eTypeClassUnion)) != 0)); | |||
1601 | } break; | |||
1602 | default: | |||
1603 | break; | |||
1604 | } | |||
1605 | ||||
1606 | if (can_parse) { | |||
1607 | if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) { | |||
1608 | auto result = | |||
1609 | std::find(type_collection.begin(), type_collection.end(), type); | |||
1610 | if (result == type_collection.end()) | |||
1611 | type_collection.push_back(type); | |||
1612 | } | |||
1613 | } | |||
1614 | ||||
1615 | auto results_up = pdb_symbol.findAllChildren(); | |||
1616 | while (auto symbol_up = results_up->getNext()) | |||
1617 | GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection); | |||
1618 | } | |||
1619 | ||||
1620 | void SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, | |||
1621 | TypeClass type_mask, | |||
1622 | lldb_private::TypeList &type_list) { | |||
1623 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
1624 | TypeCollection type_collection; | |||
1625 | CompileUnit *cu = | |||
1626 | sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr; | |||
1627 | if (cu) { | |||
1628 | auto compiland_up = GetPDBCompilandByUID(cu->GetID()); | |||
1629 | if (!compiland_up) | |||
1630 | return; | |||
1631 | GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection); | |||
1632 | } else { | |||
1633 | for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { | |||
1634 | auto cu_sp = ParseCompileUnitAtIndex(cu_idx); | |||
1635 | if (cu_sp) { | |||
1636 | if (auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID())) | |||
1637 | GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection); | |||
1638 | } | |||
1639 | } | |||
1640 | } | |||
1641 | ||||
1642 | for (auto type : type_collection) { | |||
1643 | type->GetForwardCompilerType(); | |||
1644 | type_list.Insert(type->shared_from_this()); | |||
1645 | } | |||
1646 | } | |||
1647 | ||||
1648 | llvm::Expected<lldb_private::TypeSystem &> | |||
1649 | SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { | |||
1650 | auto type_system_or_err = | |||
1651 | m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); | |||
1652 | if (type_system_or_err) { | |||
1653 | type_system_or_err->SetSymbolFile(this); | |||
1654 | } | |||
1655 | return type_system_or_err; | |||
1656 | } | |||
1657 | ||||
1658 | PDBASTParser *SymbolFilePDB::GetPDBAstParser() { | |||
1659 | auto type_system_or_err = | |||
1660 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
1661 | if (auto err = type_system_or_err.takeError()) { | |||
1662 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get PDB AST parser"); } else ::llvm::consumeError (::std::move(error_private)); } while (0) | |||
1663 | std::move(err), "Unable to get PDB AST parser")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to get PDB AST parser"); } else ::llvm::consumeError (::std::move(error_private)); } while (0); | |||
1664 | return nullptr; | |||
1665 | } | |||
1666 | ||||
1667 | auto *clang_type_system = | |||
1668 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
1669 | if (!clang_type_system) | |||
1670 | return nullptr; | |||
1671 | ||||
1672 | return clang_type_system->GetPDBParser(); | |||
1673 | } | |||
1674 | ||||
1675 | lldb_private::CompilerDeclContext | |||
1676 | SymbolFilePDB::FindNamespace(lldb_private::ConstString name, | |||
1677 | const CompilerDeclContext &parent_decl_ctx) { | |||
1678 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); | |||
1679 | auto type_system_or_err = | |||
1680 | GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); | |||
1681 | if (auto err = type_system_or_err.takeError()) { | |||
1682 | LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to find namespace {}", name.AsCString()); } else ::llvm::consumeError(::std::move(error_private)); } while (0) | |||
1683 | std::move(err), "Unable to find namespace {}",do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to find namespace {}", name.AsCString()); } else ::llvm::consumeError(::std::move(error_private)); } while (0) | |||
1684 | name.AsCString())do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to find namespace {}", name.AsCString()); } else ::llvm::consumeError(::std::move(error_private)); } while (0); | |||
1685 | return CompilerDeclContext(); | |||
1686 | } | |||
1687 | ||||
1688 | auto *clang_type_system = | |||
1689 | llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); | |||
1690 | if (!clang_type_system) | |||
1691 | return CompilerDeclContext(); | |||
1692 | ||||
1693 | PDBASTParser *pdb = clang_type_system->GetPDBParser(); | |||
1694 | if (!pdb) | |||
1695 | return CompilerDeclContext(); | |||
1696 | ||||
1697 | clang::DeclContext *decl_context = nullptr; | |||
1698 | if (parent_decl_ctx) | |||
1699 | decl_context = static_cast<clang::DeclContext *>( | |||
1700 | parent_decl_ctx.GetOpaqueDeclContext()); | |||
1701 | ||||
1702 | auto namespace_decl = | |||
1703 | pdb->FindNamespaceDecl(decl_context, name.GetStringRef()); | |||
1704 | if (!namespace_decl) | |||
1705 | return CompilerDeclContext(); | |||
1706 | ||||
1707 | return clang_type_system->CreateDeclContext(namespace_decl); | |||
1708 | } | |||
1709 | ||||
1710 | lldb_private::ConstString SymbolFilePDB::GetPluginName() { | |||
1711 | static ConstString g_name("pdb"); | |||
1712 | return g_name; | |||
1713 | } | |||
1714 | ||||
1715 | uint32_t SymbolFilePDB::GetPluginVersion() { return 1; } | |||
1716 | ||||
1717 | IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; } | |||
1718 | ||||
1719 | const IPDBSession &SymbolFilePDB::GetPDBSession() const { | |||
1720 | return *m_session_up; | |||
1721 | } | |||
1722 | ||||
1723 | lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, | |||
1724 | uint32_t index) { | |||
1725 | auto found_cu = m_comp_units.find(id); | |||
1726 | if (found_cu != m_comp_units.end()) | |||
1727 | return found_cu->second; | |||
1728 | ||||
1729 | auto compiland_up = GetPDBCompilandByUID(id); | |||
1730 | if (!compiland_up) | |||
1731 | return CompUnitSP(); | |||
1732 | ||||
1733 | lldb::LanguageType lang; | |||
1734 | auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>(); | |||
1735 | if (!details) | |||
1736 | lang = lldb::eLanguageTypeC_plus_plus; | |||
1737 | else | |||
1738 | lang = TranslateLanguage(details->getLanguage()); | |||
1739 | ||||
1740 | if (lang == lldb::LanguageType::eLanguageTypeUnknown) | |||
1741 | return CompUnitSP(); | |||
1742 | ||||
1743 | std::string path = compiland_up->getSourceFileFullPath(); | |||
1744 | if (path.empty()) | |||
1745 | return CompUnitSP(); | |||
1746 | ||||
1747 | // Don't support optimized code for now, DebugInfoPDB does not return this | |||
1748 | // information. | |||
1749 | LazyBool optimized = eLazyBoolNo; | |||
1750 | auto cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, | |||
1751 | path.c_str(), id, lang, optimized); | |||
1752 | ||||
1753 | if (!cu_sp) | |||
1754 | return CompUnitSP(); | |||
1755 | ||||
1756 | m_comp_units.insert(std::make_pair(id, cu_sp)); | |||
1757 | if (index == UINT32_MAX0xffffffffU) | |||
1758 | GetCompileUnitIndex(*compiland_up, index); | |||
1759 | lldbassert(index != UINT32_MAX)lldb_private::lldb_assert(static_cast<bool>(index != 0xffffffffU ), "index != UINT32_MAX", __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 1759); | |||
1760 | SetCompileUnitAtIndex(index, cu_sp); | |||
1761 | return cu_sp; | |||
1762 | } | |||
1763 | ||||
1764 | bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit, | |||
1765 | uint32_t match_line) { | |||
1766 | auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); | |||
1767 | if (!compiland_up) | |||
1768 | return false; | |||
1769 | ||||
1770 | // LineEntry needs the *index* of the file into the list of support files | |||
1771 | // returned by ParseCompileUnitSupportFiles. But the underlying SDK gives us | |||
1772 | // a globally unique idenfitifier in the namespace of the PDB. So, we have | |||
1773 | // to do a mapping so that we can hand out indices. | |||
1774 | llvm::DenseMap<uint32_t, uint32_t> index_map; | |||
1775 | BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map); | |||
1776 | auto line_table = std::make_unique<LineTable>(&comp_unit); | |||
1777 | ||||
1778 | // Find contributions to `compiland` from all source and header files. | |||
1779 | auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); | |||
1780 | if (!files) | |||
1781 | return false; | |||
1782 | ||||
1783 | // For each source and header file, create a LineSequence for contributions | |||
1784 | // to the compiland from that file, and add the sequence. | |||
1785 | while (auto file = files->getNext()) { | |||
1786 | std::unique_ptr<LineSequence> sequence( | |||
1787 | line_table->CreateLineSequenceContainer()); | |||
1788 | auto lines = m_session_up->findLineNumbers(*compiland_up, *file); | |||
1789 | if (!lines) | |||
1790 | continue; | |||
1791 | int entry_count = lines->getChildCount(); | |||
1792 | ||||
1793 | uint64_t prev_addr; | |||
1794 | uint32_t prev_length; | |||
1795 | uint32_t prev_line; | |||
1796 | uint32_t prev_source_idx; | |||
1797 | ||||
1798 | for (int i = 0; i < entry_count; ++i) { | |||
1799 | auto line = lines->getChildAtIndex(i); | |||
1800 | ||||
1801 | uint64_t lno = line->getLineNumber(); | |||
1802 | uint64_t addr = line->getVirtualAddress(); | |||
1803 | uint32_t length = line->getLength(); | |||
1804 | uint32_t source_id = line->getSourceFileId(); | |||
1805 | uint32_t col = line->getColumnNumber(); | |||
1806 | uint32_t source_idx = index_map[source_id]; | |||
1807 | ||||
1808 | // There was a gap between the current entry and the previous entry if | |||
1809 | // the addresses don't perfectly line up. | |||
1810 | bool is_gap = (i > 0) && (prev_addr + prev_length < addr); | |||
1811 | ||||
1812 | // Before inserting the current entry, insert a terminal entry at the end | |||
1813 | // of the previous entry's address range if the current entry resulted in | |||
1814 | // a gap from the previous entry. | |||
1815 | if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) { | |||
1816 | line_table->AppendLineEntryToSequence( | |||
1817 | sequence.get(), prev_addr + prev_length, prev_line, 0, | |||
1818 | prev_source_idx, false, false, false, false, true); | |||
1819 | ||||
1820 | line_table->InsertSequence(sequence.get()); | |||
1821 | sequence = line_table->CreateLineSequenceContainer(); | |||
1822 | } | |||
1823 | ||||
1824 | if (ShouldAddLine(match_line, lno, length)) { | |||
1825 | bool is_statement = line->isStatement(); | |||
1826 | bool is_prologue = false; | |||
1827 | bool is_epilogue = false; | |||
1828 | auto func = | |||
1829 | m_session_up->findSymbolByAddress(addr, PDB_SymType::Function); | |||
1830 | if (func) { | |||
1831 | auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>(); | |||
1832 | if (prologue) | |||
1833 | is_prologue = (addr == prologue->getVirtualAddress()); | |||
1834 | ||||
1835 | auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>(); | |||
1836 | if (epilogue) | |||
1837 | is_epilogue = (addr == epilogue->getVirtualAddress()); | |||
1838 | } | |||
1839 | ||||
1840 | line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col, | |||
1841 | source_idx, is_statement, false, | |||
1842 | is_prologue, is_epilogue, false); | |||
1843 | } | |||
1844 | ||||
1845 | prev_addr = addr; | |||
1846 | prev_length = length; | |||
1847 | prev_line = lno; | |||
1848 | prev_source_idx = source_idx; | |||
1849 | } | |||
1850 | ||||
1851 | if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) { | |||
1852 | // The end is always a terminal entry, so insert it regardless. | |||
1853 | line_table->AppendLineEntryToSequence( | |||
1854 | sequence.get(), prev_addr + prev_length, prev_line, 0, | |||
1855 | prev_source_idx, false, false, false, false, true); | |||
1856 | } | |||
1857 | ||||
1858 | line_table->InsertSequence(sequence.get()); | |||
1859 | } | |||
1860 | ||||
1861 | if (line_table->GetSize()) { | |||
1862 | comp_unit.SetLineTable(line_table.release()); | |||
1863 | return true; | |||
1864 | } | |||
1865 | return false; | |||
1866 | } | |||
1867 | ||||
1868 | void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap( | |||
1869 | const PDBSymbolCompiland &compiland, | |||
1870 | llvm::DenseMap<uint32_t, uint32_t> &index_map) const { | |||
1871 | // This is a hack, but we need to convert the source id into an index into | |||
1872 | // the support files array. We don't want to do path comparisons to avoid | |||
1873 | // basename / full path issues that may or may not even be a problem, so we | |||
1874 | // use the globally unique source file identifiers. Ideally we could use the | |||
1875 | // global identifiers everywhere, but LineEntry currently assumes indices. | |||
1876 | auto source_files = m_session_up->getSourceFilesForCompiland(compiland); | |||
1877 | if (!source_files) | |||
1878 | return; | |||
1879 | ||||
1880 | int index = 0; | |||
1881 | while (auto file = source_files->getNext()) { | |||
1882 | uint32_t source_id = file->getUniqueId(); | |||
1883 | index_map[source_id] = index++; | |||
1884 | } | |||
1885 | } | |||
1886 | ||||
1887 | lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress( | |||
1888 | const lldb_private::Address &so_addr) { | |||
1889 | lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); | |||
1890 | if (file_vm_addr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL || file_vm_addr == 0) | |||
1891 | return nullptr; | |||
1892 | ||||
1893 | // If it is a PDB function's vm addr, this is the first sure bet. | |||
1894 | if (auto lines = | |||
1895 | m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/1)) { | |||
1896 | if (auto first_line = lines->getNext()) | |||
1897 | return ParseCompileUnitForUID(first_line->getCompilandId()); | |||
1898 | } | |||
1899 | ||||
1900 | // Otherwise we resort to section contributions. | |||
1901 | if (auto sec_contribs = m_session_up->getSectionContribs()) { | |||
1902 | while (auto section = sec_contribs->getNext()) { | |||
1903 | auto va = section->getVirtualAddress(); | |||
1904 | if (file_vm_addr >= va && file_vm_addr < va + section->getLength()) | |||
1905 | return ParseCompileUnitForUID(section->getCompilandId()); | |||
1906 | } | |||
1907 | } | |||
1908 | return nullptr; | |||
1909 | } | |||
1910 | ||||
1911 | Mangled | |||
1912 | SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) { | |||
1913 | Mangled mangled; | |||
1914 | auto func_name = pdb_func.getName(); | |||
1915 | auto func_undecorated_name = pdb_func.getUndecoratedName(); | |||
1916 | std::string func_decorated_name; | |||
1917 | ||||
1918 | // Seek from public symbols for non-static function's decorated name if any. | |||
1919 | // For static functions, they don't have undecorated names and aren't exposed | |||
1920 | // in Public Symbols either. | |||
1921 | if (!func_undecorated_name.empty()) { | |||
1922 | auto result_up = m_global_scope_up->findChildren( | |||
1923 | PDB_SymType::PublicSymbol, func_undecorated_name, | |||
1924 | PDB_NameSearchFlags::NS_UndecoratedName); | |||
1925 | if (result_up) { | |||
1926 | while (auto symbol_up = result_up->getNext()) { | |||
1927 | // For a public symbol, it is unique. | |||
1928 | lldbassert(result_up->getChildCount() == 1)lldb_private::lldb_assert(static_cast<bool>(result_up-> getChildCount() == 1), "result_up->getChildCount() == 1", __FUNCTION__ , "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , 1928); | |||
1929 | if (auto *pdb_public_sym = | |||
1930 | llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>( | |||
1931 | symbol_up.get())) { | |||
1932 | if (pdb_public_sym->isFunction()) { | |||
1933 | func_decorated_name = pdb_public_sym->getName(); | |||
1934 | break; | |||
1935 | } | |||
1936 | } | |||
1937 | } | |||
1938 | } | |||
1939 | } | |||
1940 | if (!func_decorated_name.empty()) { | |||
1941 | mangled.SetMangledName(ConstString(func_decorated_name)); | |||
1942 | ||||
1943 | // For MSVC, format of C funciton's decorated name depends on calling | |||
1944 | // convention. Unfortunately none of the format is recognized by current | |||
1945 | // LLDB. For example, `_purecall` is a __cdecl C function. From PDB, | |||
1946 | // `__purecall` is retrieved as both its decorated and undecorated name | |||
1947 | // (using PDBSymbolFunc::getUndecoratedName method). However `__purecall` | |||
1948 | // string is not treated as mangled in LLDB (neither `?` nor `_Z` prefix). | |||
1949 | // Mangled::GetDemangledName method will fail internally and caches an | |||
1950 | // empty string as its undecorated name. So we will face a contradiction | |||
1951 | // here for the same symbol: | |||
1952 | // non-empty undecorated name from PDB | |||
1953 | // empty undecorated name from LLDB | |||
1954 | if (!func_undecorated_name.empty() && mangled.GetDemangledName().IsEmpty()) | |||
1955 | mangled.SetDemangledName(ConstString(func_undecorated_name)); | |||
1956 | ||||
1957 | // LLDB uses several flags to control how a C++ decorated name is | |||
1958 | // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. So the | |||
1959 | // yielded name could be different from what we retrieve from | |||
1960 | // PDB source unless we also apply same flags in getting undecorated | |||
1961 | // name through PDBSymbolFunc::getUndecoratedNameEx method. | |||
1962 | if (!func_undecorated_name.empty() && | |||
1963 | mangled.GetDemangledName() != ConstString(func_undecorated_name)) | |||
1964 | mangled.SetDemangledName(ConstString(func_undecorated_name)); | |||
1965 | } else if (!func_undecorated_name.empty()) { | |||
1966 | mangled.SetDemangledName(ConstString(func_undecorated_name)); | |||
1967 | } else if (!func_name.empty()) | |||
1968 | mangled.SetValue(ConstString(func_name), false); | |||
1969 | ||||
1970 | return mangled; | |||
1971 | } | |||
1972 | ||||
1973 | bool SymbolFilePDB::DeclContextMatchesThisSymbolFile( | |||
1974 | const lldb_private::CompilerDeclContext &decl_ctx) { | |||
1975 | if (!decl_ctx.IsValid()) | |||
1976 | return true; | |||
1977 | ||||
1978 | TypeSystem *decl_ctx_type_system = decl_ctx.GetTypeSystem(); | |||
1979 | if (!decl_ctx_type_system) | |||
1980 | return false; | |||
1981 | auto type_system_or_err = GetTypeSystemForLanguage( | |||
1982 | decl_ctx_type_system->GetMinimumLanguage(nullptr)); | |||
1983 | if (auto err = type_system_or_err.takeError()) { | |||
1984 | LLDB_LOG_ERROR(do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to determine if DeclContext matches this symbol file" ); } else ::llvm::consumeError(::std::move(error_private)); } while (0) | |||
1985 | lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to determine if DeclContext matches this symbol file" ); } else ::llvm::consumeError(::std::move(error_private)); } while (0) | |||
1986 | std::move(err),do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to determine if DeclContext matches this symbol file" ); } else ::llvm::consumeError(::std::move(error_private)); } while (0) | |||
1987 | "Unable to determine if DeclContext matches this symbol file")do { ::lldb_private::Log *log_private = (lldb_private::GetLogIfAnyCategoriesSet ((1u << 20))); ::llvm::Error error_private = (std::move (err)); if (log_private && error_private) { log_private ->FormatError(::std::move(error_private), "/usr/src/gnu/usr.bin/clang/liblldbPluginSymbolFile/../../../llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp" , __func__, "Unable to determine if DeclContext matches this symbol file" ); } else ::llvm::consumeError(::std::move(error_private)); } while (0); | |||
1988 | return false; | |||
1989 | } | |||
1990 | ||||
1991 | if (decl_ctx_type_system == &type_system_or_err.get()) | |||
1992 | return true; // The type systems match, return true | |||
1993 | ||||
1994 | return false; | |||
1995 | } | |||
1996 | ||||
1997 | uint32_t SymbolFilePDB::GetCompilandId(const llvm::pdb::PDBSymbolData &data) { | |||
1998 | static const auto pred_upper = [](uint32_t lhs, SecContribInfo rhs) { | |||
1999 | return lhs < rhs.Offset; | |||
2000 | }; | |||
2001 | ||||
2002 | // Cache section contributions | |||
2003 | if (m_sec_contribs.empty()) { | |||
2004 | if (auto SecContribs = m_session_up->getSectionContribs()) { | |||
2005 | while (auto SectionContrib = SecContribs->getNext()) { | |||
2006 | auto comp_id = SectionContrib->getCompilandId(); | |||
2007 | if (!comp_id) | |||
2008 | continue; | |||
2009 | ||||
2010 | auto sec = SectionContrib->getAddressSection(); | |||
2011 | auto &sec_cs = m_sec_contribs[sec]; | |||
2012 | ||||
2013 | auto offset = SectionContrib->getAddressOffset(); | |||
2014 | auto it = | |||
2015 | std::upper_bound(sec_cs.begin(), sec_cs.end(), offset, pred_upper); | |||
2016 | ||||
2017 | auto size = SectionContrib->getLength(); | |||
2018 | sec_cs.insert(it, {offset, size, comp_id}); | |||
2019 | } | |||
2020 | } | |||
2021 | } | |||
2022 | ||||
2023 | // Check by line number | |||
2024 | if (auto Lines = data.getLineNumbers()) { | |||
2025 | if (auto FirstLine = Lines->getNext()) | |||
2026 | return FirstLine->getCompilandId(); | |||
2027 | } | |||
2028 | ||||
2029 | // Retrieve section + offset | |||
2030 | uint32_t DataSection = data.getAddressSection(); | |||
2031 | uint32_t DataOffset = data.getAddressOffset(); | |||
2032 | if (DataSection == 0) { | |||
2033 | if (auto RVA = data.getRelativeVirtualAddress()) | |||
2034 | m_session_up->addressForRVA(RVA, DataSection, DataOffset); | |||
2035 | } | |||
2036 | ||||
2037 | if (DataSection) { | |||
2038 | // Search by section contributions | |||
2039 | auto &sec_cs = m_sec_contribs[DataSection]; | |||
2040 | auto it = | |||
2041 | std::upper_bound(sec_cs.begin(), sec_cs.end(), DataOffset, pred_upper); | |||
2042 | if (it != sec_cs.begin()) { | |||
2043 | --it; | |||
2044 | if (DataOffset < it->Offset + it->Size) | |||
2045 | return it->CompilandId; | |||
2046 | } | |||
2047 | } else { | |||
2048 | // Search in lexical tree | |||
2049 | auto LexParentId = data.getLexicalParentId(); | |||
2050 | while (auto LexParent = m_session_up->getSymbolById(LexParentId)) { | |||
2051 | if (LexParent->getSymTag() == PDB_SymType::Exe) | |||
2052 | break; | |||
2053 | if (LexParent->getSymTag() == PDB_SymType::Compiland) | |||
2054 | return LexParentId; | |||
2055 | LexParentId = LexParent->getRawSymbol().getLexicalParentId(); | |||
2056 | } | |||
2057 | } | |||
2058 | ||||
2059 | return 0; | |||
2060 | } |
1 | //===-- CompilerDeclContext.h -----------------------------------*- C++ -*-===// |
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 | #ifndef LLDB_SYMBOL_COMPILERDECLCONTEXT_H |
10 | #define LLDB_SYMBOL_COMPILERDECLCONTEXT_H |
11 | |
12 | #include <vector> |
13 | |
14 | #include "lldb/Utility/ConstString.h" |
15 | #include "lldb/lldb-private.h" |
16 | |
17 | namespace lldb_private { |
18 | |
19 | /// Represents a generic declaration context in a program. A declaration context |
20 | /// is data structure that contains declarations (e.g. namespaces). |
21 | /// |
22 | /// This class serves as an abstraction for a declaration context inside one of |
23 | /// the TypeSystems implemented by the language plugins. It does not have any |
24 | /// actual logic in it but only stores an opaque pointer and a pointer to the |
25 | /// TypeSystem that gives meaning to this opaque pointer. All methods of this |
26 | /// class should call their respective method in the TypeSystem interface and |
27 | /// pass the opaque pointer along. |
28 | /// |
29 | /// \see lldb_private::TypeSystem |
30 | class CompilerDeclContext { |
31 | public: |
32 | /// Constructs an invalid CompilerDeclContext. |
33 | CompilerDeclContext() = default; |
34 | |
35 | /// Constructs a CompilerDeclContext with the given opaque decl context |
36 | /// and its respective TypeSystem instance. |
37 | /// |
38 | /// This constructor should only be called from the respective TypeSystem |
39 | /// implementation. |
40 | /// |
41 | /// \see lldb_private::TypeSystemClang::CreateDeclContext(clang::DeclContext*) |
42 | CompilerDeclContext(TypeSystem *type_system, void *decl_ctx) |
43 | : m_type_system(type_system), m_opaque_decl_ctx(decl_ctx) {} |
44 | |
45 | // Tests |
46 | |
47 | explicit operator bool() const { return IsValid(); } |
48 | |
49 | bool operator<(const CompilerDeclContext &rhs) const { |
50 | if (m_type_system == rhs.m_type_system) |
51 | return m_opaque_decl_ctx < rhs.m_opaque_decl_ctx; |
52 | return m_type_system < rhs.m_type_system; |
53 | } |
54 | |
55 | bool IsValid() const { |
56 | return m_type_system != nullptr && m_opaque_decl_ctx != nullptr; |
57 | } |
58 | |
59 | std::vector<CompilerDecl> FindDeclByName(ConstString name, |
60 | const bool ignore_using_decls); |
61 | |
62 | /// Checks if this decl context represents a method of a class. |
63 | /// |
64 | /// \param[out] language_ptr |
65 | /// If non NULL and \b true is returned from this function, |
66 | /// this will indicate if the language that respresents the method. |
67 | /// |
68 | /// \param[out] is_instance_method_ptr |
69 | /// If non NULL and \b true is returned from this function, |
70 | /// this will indicate if the method is an instance function (true) |
71 | /// or a class method (false indicating the function is static, or |
72 | /// doesn't require an instance of the class to be called). |
73 | /// |
74 | /// \param[out] language_object_name_ptr |
75 | /// If non NULL and \b true is returned from this function, |
76 | /// this will indicate if implicit object name for the language |
77 | /// like "this" for C++, and "self" for Objective C. |
78 | /// |
79 | /// \return |
80 | /// Returns true if this is a decl context that represents a method |
81 | /// in a struct, union or class. |
82 | bool IsClassMethod(lldb::LanguageType *language_ptr, |
83 | bool *is_instance_method_ptr, |
84 | ConstString *language_object_name_ptr); |
85 | |
86 | /// Check if the given other decl context is contained in the lookup |
87 | /// of this decl context (for example because the other context is a nested |
88 | /// inline namespace). |
89 | /// |
90 | /// @param[in] other |
91 | /// The other decl context for which we should check if it is contained |
92 | /// in the lookoup of this context. |
93 | /// |
94 | /// @return |
95 | /// Returns true iff the other decl context is contained in the lookup |
96 | /// of this decl context. |
97 | bool IsContainedInLookup(CompilerDeclContext other) const; |
98 | |
99 | // Accessors |
100 | |
101 | TypeSystem *GetTypeSystem() const { return m_type_system; } |
102 | |
103 | void *GetOpaqueDeclContext() const { return m_opaque_decl_ctx; } |
104 | |
105 | void SetDeclContext(TypeSystem *type_system, void *decl_ctx) { |
106 | m_type_system = type_system; |
107 | m_opaque_decl_ctx = decl_ctx; |
108 | } |
109 | |
110 | void Clear() { |
111 | m_type_system = nullptr; |
112 | m_opaque_decl_ctx = nullptr; |
113 | } |
114 | |
115 | ConstString GetName() const; |
116 | |
117 | ConstString GetScopeQualifiedName() const; |
118 | |
119 | private: |
120 | TypeSystem *m_type_system = nullptr; |
121 | void *m_opaque_decl_ctx = nullptr; |
122 | }; |
123 | |
124 | bool operator==(const CompilerDeclContext &lhs, const CompilerDeclContext &rhs); |
125 | bool operator!=(const CompilerDeclContext &lhs, const CompilerDeclContext &rhs); |
126 | |
127 | } // namespace lldb_private |
128 | |
129 | #endif // LLDB_SYMBOL_COMPILERDECLCONTEXT_H |
1 | //===-- ConstString.h -------------------------------------------*- C++ -*-===// |
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 | #ifndef LLDB_UTILITY_CONSTSTRING_H |
10 | #define LLDB_UTILITY_CONSTSTRING_H |
11 | |
12 | #include "llvm/ADT/DenseMapInfo.h" |
13 | #include "llvm/ADT/StringRef.h" |
14 | #include "llvm/Support/FormatVariadic.h" |
15 | #include "llvm/Support/YAMLTraits.h" |
16 | |
17 | #include <cstddef> |
18 | |
19 | namespace lldb_private { |
20 | class Stream; |
21 | } |
22 | namespace llvm { |
23 | class raw_ostream; |
24 | } |
25 | |
26 | namespace lldb_private { |
27 | |
28 | /// \class ConstString ConstString.h "lldb/Utility/ConstString.h" |
29 | /// A uniqued constant string class. |
30 | /// |
31 | /// Provides an efficient way to store strings as uniqued strings. After the |
32 | /// strings are uniqued, finding strings that are equal to one another is very |
33 | /// fast as just the pointers need to be compared. It also allows for many |
34 | /// common strings from many different sources to be shared to keep the memory |
35 | /// footprint low. |
36 | /// |
37 | /// No reference counting is done on strings that are added to the string |
38 | /// pool, once strings are added they are in the string pool for the life of |
39 | /// the program. |
40 | class ConstString { |
41 | public: |
42 | /// Default constructor |
43 | /// |
44 | /// Initializes the string to an empty string. |
45 | ConstString() = default; |
46 | |
47 | explicit ConstString(const llvm::StringRef &s); |
48 | |
49 | /// Construct with C String value |
50 | /// |
51 | /// Constructs this object with a C string by looking to see if the |
52 | /// C string already exists in the global string pool. If it doesn't |
53 | /// exist, it is added to the string pool. |
54 | /// |
55 | /// \param[in] cstr |
56 | /// A NULL terminated C string to add to the string pool. |
57 | explicit ConstString(const char *cstr); |
58 | |
59 | /// Construct with C String value with max length |
60 | /// |
61 | /// Constructs this object with a C string with a length. If \a max_cstr_len |
62 | /// is greater than the actual length of the string, the string length will |
63 | /// be truncated. This allows substrings to be created without the need to |
64 | /// NULL terminate the string as it is passed into this function. |
65 | /// |
66 | /// \param[in] cstr |
67 | /// A pointer to the first character in the C string. The C |
68 | /// string can be NULL terminated in a buffer that contains |
69 | /// more characters than the length of the string, or the |
70 | /// string can be part of another string and a new substring |
71 | /// can be created. |
72 | /// |
73 | /// \param[in] max_cstr_len |
74 | /// The max length of \a cstr. If the string length of \a cstr |
75 | /// is less than \a max_cstr_len, then the string will be |
76 | /// truncated. If the string length of \a cstr is greater than |
77 | /// \a max_cstr_len, then only max_cstr_len bytes will be used |
78 | /// from \a cstr. |
79 | explicit ConstString(const char *cstr, size_t max_cstr_len); |
80 | |
81 | /// C string equality binary predicate function object for ConstString |
82 | /// objects. |
83 | struct StringIsEqual { |
84 | /// C equality test. |
85 | /// |
86 | /// Two C strings are equal when they are contained in ConstString objects |
87 | /// when their pointer values are equal to each other. |
88 | /// |
89 | /// \return |
90 | /// Returns \b true if the C string in \a lhs is equal to |
91 | /// the C string value in \a rhs, \b false otherwise. |
92 | bool operator()(const char *lhs, const char *rhs) const { |
93 | return lhs == rhs; |
94 | } |
95 | }; |
96 | |
97 | /// Convert to bool operator. |
98 | /// |
99 | /// This allows code to check a ConstString object to see if it contains a |
100 | /// valid string using code such as: |
101 | /// |
102 | /// \code |
103 | /// ConstString str(...); |
104 | /// if (str) |
105 | /// { ... |
106 | /// \endcode |
107 | /// |
108 | /// \return |
109 | /// /b True this object contains a valid non-empty C string, \b |
110 | /// false otherwise. |
111 | explicit operator bool() const { return !IsEmpty(); } |
112 | |
113 | /// Equal to operator |
114 | /// |
115 | /// Returns true if this string is equal to the string in \a rhs. This |
116 | /// operation is very fast as it results in a pointer comparison since all |
117 | /// strings are in a uniqued in a global string pool. |
118 | /// |
119 | /// \param[in] rhs |
120 | /// Another string object to compare this object to. |
121 | /// |
122 | /// \return |
123 | /// true if this object is equal to \a rhs. |
124 | /// false if this object is not equal to \a rhs. |
125 | bool operator==(ConstString rhs) const { |
126 | // We can do a pointer compare to compare these strings since they must |
127 | // come from the same pool in order to be equal. |
128 | return m_string == rhs.m_string; |
129 | } |
130 | |
131 | /// Equal to operator against a non-ConstString value. |
132 | /// |
133 | /// Returns true if this string is equal to the string in \a rhs. This |
134 | /// overload is usually slower than comparing against a ConstString value. |
135 | /// However, if the rhs string not already a ConstString and it is impractical |
136 | /// to turn it into a non-temporary variable, then this overload is faster. |
137 | /// |
138 | /// \param[in] rhs |
139 | /// Another string object to compare this object to. |
140 | /// |
141 | /// \return |
142 | /// \b true if this object is equal to \a rhs. |
143 | /// \b false if this object is not equal to \a rhs. |
144 | bool operator==(const char *rhs) const { |
145 | // ConstString differentiates between empty strings and nullptr strings, but |
146 | // StringRef doesn't. Therefore we have to do this check manually now. |
147 | if (m_string == nullptr && rhs != nullptr) |
148 | return false; |
149 | if (m_string != nullptr && rhs == nullptr) |
150 | return false; |
151 | |
152 | return GetStringRef() == rhs; |
153 | } |
154 | |
155 | /// Not equal to operator |
156 | /// |
157 | /// Returns true if this string is not equal to the string in \a rhs. This |
158 | /// operation is very fast as it results in a pointer comparison since all |
159 | /// strings are in a uniqued in a global string pool. |
160 | /// |
161 | /// \param[in] rhs |
162 | /// Another string object to compare this object to. |
163 | /// |
164 | /// \return |
165 | /// \b true if this object is not equal to \a rhs. |
166 | /// \b false if this object is equal to \a rhs. |
167 | bool operator!=(ConstString rhs) const { return m_string != rhs.m_string; } |
168 | |
169 | /// Not equal to operator against a non-ConstString value. |
170 | /// |
171 | /// Returns true if this string is not equal to the string in \a rhs. This |
172 | /// overload is usually slower than comparing against a ConstString value. |
173 | /// However, if the rhs string not already a ConstString and it is impractical |
174 | /// to turn it into a non-temporary variable, then this overload is faster. |
175 | /// |
176 | /// \param[in] rhs |
177 | /// Another string object to compare this object to. |
178 | /// |
179 | /// \return \b true if this object is not equal to \a rhs, false otherwise. |
180 | bool operator!=(const char *rhs) const { return !(*this == rhs); } |
181 | |
182 | bool operator<(ConstString rhs) const; |
183 | |
184 | /// Get the string value as a C string. |
185 | /// |
186 | /// Get the value of the contained string as a NULL terminated C string |
187 | /// value. |
188 | /// |
189 | /// If \a value_if_empty is nullptr, then nullptr will be returned. |
190 | /// |
191 | /// \return Returns \a value_if_empty if the string is empty, otherwise |
192 | /// the C string value contained in this object. |
193 | const char *AsCString(const char *value_if_empty = nullptr) const { |
194 | return (IsEmpty() ? value_if_empty : m_string); |
195 | } |
196 | |
197 | /// Get the string value as a llvm::StringRef |
198 | /// |
199 | /// \return |
200 | /// Returns a new llvm::StringRef object filled in with the |
201 | /// needed data. |
202 | llvm::StringRef GetStringRef() const { |
203 | return llvm::StringRef(m_string, GetLength()); |
204 | } |
205 | |
206 | /// Get the string value as a C string. |
207 | /// |
208 | /// Get the value of the contained string as a NULL terminated C string |
209 | /// value. Similar to the ConstString::AsCString() function, yet this |
210 | /// function will always return nullptr if the string is not valid. So this |
211 | /// function is a direct accessor to the string pointer value. |
212 | /// |
213 | /// \return |
214 | /// Returns nullptr the string is invalid, otherwise the C string |
215 | /// value contained in this object. |
216 | const char *GetCString() const { return m_string; } |
217 | |
218 | /// Get the length in bytes of string value. |
219 | /// |
220 | /// The string pool stores the length of the string, so we can avoid calling |
221 | /// strlen() on the pointer value with this function. |
222 | /// |
223 | /// \return |
224 | /// Returns the number of bytes that this string occupies in |
225 | /// memory, not including the NULL termination byte. |
226 | size_t GetLength() const; |
227 | |
228 | /// Clear this object's state. |
229 | /// |
230 | /// Clear any contained string and reset the value to the empty string |
231 | /// value. |
232 | void Clear() { m_string = nullptr; } |
233 | |
234 | /// Equal to operator |
235 | /// |
236 | /// Returns true if this string is equal to the string in \a rhs. If case |
237 | /// sensitive equality is tested, this operation is very fast as it results |
238 | /// in a pointer comparison since all strings are in a uniqued in a global |
239 | /// string pool. |
240 | /// |
241 | /// \param[in] lhs |
242 | /// The Left Hand Side const ConstString object reference. |
243 | /// |
244 | /// \param[in] rhs |
245 | /// The Right Hand Side const ConstString object reference. |
246 | /// |
247 | /// \param[in] case_sensitive |
248 | /// Case sensitivity. If true, case sensitive equality |
249 | /// will be tested, otherwise character case will be ignored |
250 | /// |
251 | /// \return \b true if this object is equal to \a rhs, \b false otherwise. |
252 | static bool Equals(ConstString lhs, ConstString rhs, |
253 | const bool case_sensitive = true); |
254 | |
255 | /// Compare two string objects. |
256 | /// |
257 | /// Compares the C string values contained in \a lhs and \a rhs and returns |
258 | /// an integer result. |
259 | /// |
260 | /// NOTE: only call this function when you want a true string |
261 | /// comparison. If you want string equality use the, use the == operator as |
262 | /// it is much more efficient. Also if you want string inequality, use the |
263 | /// != operator for the same reasons. |
264 | /// |
265 | /// \param[in] lhs |
266 | /// The Left Hand Side const ConstString object reference. |
267 | /// |
268 | /// \param[in] rhs |
269 | /// The Right Hand Side const ConstString object reference. |
270 | /// |
271 | /// \param[in] case_sensitive |
272 | /// Case sensitivity of compare. If true, case sensitive compare |
273 | /// will be performed, otherwise character case will be ignored |
274 | /// |
275 | /// \return -1 if lhs < rhs, 0 if lhs == rhs, 1 if lhs > rhs |
276 | static int Compare(ConstString lhs, ConstString rhs, |
277 | const bool case_sensitive = true); |
278 | |
279 | /// Dump the object description to a stream. |
280 | /// |
281 | /// Dump the string value to the stream \a s. If the contained string is |
282 | /// empty, print \a value_if_empty to the stream instead. If \a |
283 | /// value_if_empty is nullptr, then nothing will be dumped to the stream. |
284 | /// |
285 | /// \param[in] s |
286 | /// The stream that will be used to dump the object description. |
287 | /// |
288 | /// \param[in] value_if_empty |
289 | /// The value to dump if the string is empty. If nullptr, nothing |
290 | /// will be output to the stream. |
291 | void Dump(Stream *s, const char *value_if_empty = nullptr) const; |
292 | |
293 | /// Dump the object debug description to a stream. |
294 | /// |
295 | /// \param[in] s |
296 | /// The stream that will be used to dump the object description. |
297 | void DumpDebug(Stream *s) const; |
298 | |
299 | /// Test for empty string. |
300 | /// |
301 | /// \return |
302 | /// \b true if the contained string is empty. |
303 | /// \b false if the contained string is not empty. |
304 | bool IsEmpty() const { return m_string == nullptr || m_string[0] == '\0'; } |
305 | |
306 | /// Test for null string. |
307 | /// |
308 | /// \return |
309 | /// \b true if there is no string associated with this instance. |
310 | /// \b false if there is a string associated with this instance. |
311 | bool IsNull() const { return m_string == nullptr; } |
312 | |
313 | /// Set the C string value. |
314 | /// |
315 | /// Set the string value in the object by uniquing the \a cstr string value |
316 | /// in our global string pool. |
317 | /// |
318 | /// If the C string already exists in the global string pool, it finds the |
319 | /// current entry and returns the existing value. If it doesn't exist, it is |
320 | /// added to the string pool. |
321 | /// |
322 | /// \param[in] cstr |
323 | /// A NULL terminated C string to add to the string pool. |
324 | void SetCString(const char *cstr); |
325 | |
326 | void SetString(const llvm::StringRef &s); |
327 | |
328 | /// Set the C string value and its mangled counterpart. |
329 | /// |
330 | /// Object files and debug symbols often use mangled string to represent the |
331 | /// linkage name for a symbol, function or global. The string pool can |
332 | /// efficiently store these values and their counterparts so when we run |
333 | /// into another instance of a mangled name, we can avoid calling the name |
334 | /// demangler over and over on the same strings and then trying to unique |
335 | /// them. |
336 | /// |
337 | /// \param[in] demangled |
338 | /// The demangled string to correlate with the \a mangled name. |
339 | /// |
340 | /// \param[in] mangled |
341 | /// The already uniqued mangled ConstString to correlate the |
342 | /// soon to be uniqued version of \a demangled. |
343 | void SetStringWithMangledCounterpart(llvm::StringRef demangled, |
344 | ConstString mangled); |
345 | |
346 | /// Retrieve the mangled or demangled counterpart for a mangled or demangled |
347 | /// ConstString. |
348 | /// |
349 | /// Object files and debug symbols often use mangled string to represent the |
350 | /// linkage name for a symbol, function or global. The string pool can |
351 | /// efficiently store these values and their counterparts so when we run |
352 | /// into another instance of a mangled name, we can avoid calling the name |
353 | /// demangler over and over on the same strings and then trying to unique |
354 | /// them. |
355 | /// |
356 | /// \param[in] counterpart |
357 | /// A reference to a ConstString object that might get filled in |
358 | /// with the demangled/mangled counterpart. |
359 | /// |
360 | /// \return |
361 | /// /b True if \a counterpart was filled in with the counterpart |
362 | /// /b false otherwise. |
363 | bool GetMangledCounterpart(ConstString &counterpart) const; |
364 | |
365 | /// Set the C string value with length. |
366 | /// |
367 | /// Set the string value in the object by uniquing \a cstr_len bytes |
368 | /// starting at the \a cstr string value in our global string pool. If trim |
369 | /// is true, then \a cstr_len indicates a maximum length of the CString and |
370 | /// if the actual length of the string is less, then it will be trimmed. |
371 | /// |
372 | /// If the C string already exists in the global string pool, it finds the |
373 | /// current entry and returns the existing value. If it doesn't exist, it is |
374 | /// added to the string pool. |
375 | /// |
376 | /// \param[in] cstr |
377 | /// A NULL terminated C string to add to the string pool. |
378 | /// |
379 | /// \param[in] cstr_len |
380 | /// The maximum length of the C string. |
381 | void SetCStringWithLength(const char *cstr, size_t cstr_len); |
382 | |
383 | /// Set the C string value with the minimum length between \a fixed_cstr_len |
384 | /// and the actual length of the C string. This can be used for data |
385 | /// structures that have a fixed length to store a C string where the string |
386 | /// might not be NULL terminated if the string takes the entire buffer. |
387 | void SetTrimmedCStringWithLength(const char *cstr, size_t fixed_cstr_len); |
388 | |
389 | /// Get the memory cost of this object. |
390 | /// |
391 | /// Return the size in bytes that this object takes in memory. This returns |
392 | /// the size in bytes of this object, which does not include any the shared |
393 | /// string values it may refer to. |
394 | /// |
395 | /// \return |
396 | /// The number of bytes that this object occupies in memory. |
397 | /// |
398 | /// \see ConstString::StaticMemorySize () |
399 | size_t MemorySize() const { return sizeof(ConstString); } |
400 | |
401 | /// Get the size in bytes of the current global string pool. |
402 | /// |
403 | /// Reports the size in bytes of all shared C string values, containers and |
404 | /// any other values as a byte size for the entire string pool. |
405 | /// |
406 | /// \return |
407 | /// The number of bytes that the global string pool occupies |
408 | /// in memory. |
409 | static size_t StaticMemorySize(); |
410 | |
411 | protected: |
412 | template <typename T> friend struct ::llvm::DenseMapInfo; |
413 | /// Only used by DenseMapInfo. |
414 | static ConstString FromStringPoolPointer(const char *ptr) { |
415 | ConstString s; |
416 | s.m_string = ptr; |
417 | return s; |
418 | }; |
419 | |
420 | const char *m_string = nullptr; |
421 | }; |
422 | |
423 | /// Stream the string value \a str to the stream \a s |
424 | Stream &operator<<(Stream &s, ConstString str); |
425 | |
426 | } // namespace lldb_private |
427 | |
428 | namespace llvm { |
429 | template <> struct format_provider<lldb_private::ConstString> { |
430 | static void format(const lldb_private::ConstString &CS, llvm::raw_ostream &OS, |
431 | llvm::StringRef Options); |
432 | }; |
433 | |
434 | /// DenseMapInfo implementation. |
435 | /// \{ |
436 | template <> struct DenseMapInfo<lldb_private::ConstString> { |
437 | static inline lldb_private::ConstString getEmptyKey() { |
438 | return lldb_private::ConstString::FromStringPoolPointer( |
439 | DenseMapInfo<const char *>::getEmptyKey()); |
440 | } |
441 | static inline lldb_private::ConstString getTombstoneKey() { |
442 | return lldb_private::ConstString::FromStringPoolPointer( |
443 | DenseMapInfo<const char *>::getTombstoneKey()); |
444 | } |
445 | static unsigned getHashValue(lldb_private::ConstString val) { |
446 | return DenseMapInfo<const char *>::getHashValue(val.m_string); |
447 | } |
448 | static bool isEqual(lldb_private::ConstString LHS, |
449 | lldb_private::ConstString RHS) { |
450 | return LHS == RHS; |
451 | } |
452 | }; |
453 | /// \} |
454 | |
455 | namespace yaml { |
456 | template <> struct ScalarTraits<lldb_private::ConstString> { |
457 | static void output(const lldb_private::ConstString &, void *, raw_ostream &); |
458 | static StringRef input(StringRef, void *, lldb_private::ConstString &); |
459 | static QuotingType mustQuote(StringRef S) { return QuotingType::Double; } |
460 | }; |
461 | } // namespace yaml |
462 | |
463 | inline raw_ostream &operator<<(raw_ostream &os, lldb_private::ConstString s) { |
464 | os << s.GetStringRef(); |
465 | return os; |
466 | } |
467 | } // namespace llvm |
468 | |
469 | LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ConstString)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <lldb_private::ConstString>::value && !std::is_same <lldb_private::ConstString, std::string>::value && !std::is_same<lldb_private::ConstString, llvm::StringRef> ::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<lldb_private ::ConstString> { static const bool flow = false; }; } } |
470 | |
471 | #endif // LLDB_UTILITY_CONSTSTRING_H |
1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H |
11 | #define _LIBCPP___MEMORY_UNIQUE_PTR_H |
12 | |
13 | #include <__config> |
14 | #include <__functional_base> |
15 | #include <__functional/hash.h> |
16 | #include <__functional/operations.h> |
17 | #include <__memory/allocator_traits.h> // __pointer |
18 | #include <__memory/compressed_pair.h> |
19 | #include <__utility/forward.h> |
20 | #include <cstddef> |
21 | #include <type_traits> |
22 | #include <utility> |
23 | |
24 | #if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
25 | # include <__memory/auto_ptr.h> |
26 | #endif |
27 | |
28 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
29 | #pragma GCC system_header |
30 | #endif |
31 | |
32 | _LIBCPP_PUSH_MACROSpush_macro("min") push_macro("max") |
33 | #include <__undef_macros> |
34 | |
35 | _LIBCPP_BEGIN_NAMESPACE_STDnamespace std { inline namespace __1 { |
36 | |
37 | template <class _Tp> |
38 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) default_delete { |
39 | static_assert(!is_function<_Tp>::value, |
40 | "default_delete cannot be instantiated for function types"); |
41 | #ifndef _LIBCPP_CXX03_LANG |
42 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) constexpr default_delete() _NOEXCEPTnoexcept = default; |
43 | #else |
44 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) default_delete() {} |
45 | #endif |
46 | template <class _Up> |
47 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
48 | default_delete(const default_delete<_Up>&, |
49 | typename enable_if<is_convertible<_Up*, _Tp*>::value>::type* = |
50 | 0) _NOEXCEPTnoexcept {} |
51 | |
52 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) void operator()(_Tp* __ptr) const _NOEXCEPTnoexcept { |
53 | static_assert(sizeof(_Tp) > 0, |
54 | "default_delete can not delete incomplete type"); |
55 | static_assert(!is_void<_Tp>::value, |
56 | "default_delete can not delete incomplete type"); |
57 | delete __ptr; |
58 | } |
59 | }; |
60 | |
61 | template <class _Tp> |
62 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) default_delete<_Tp[]> { |
63 | private: |
64 | template <class _Up> |
65 | struct _EnableIfConvertible |
66 | : enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value> {}; |
67 | |
68 | public: |
69 | #ifndef _LIBCPP_CXX03_LANG |
70 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) constexpr default_delete() _NOEXCEPTnoexcept = default; |
71 | #else |
72 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) default_delete() {} |
73 | #endif |
74 | |
75 | template <class _Up> |
76 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
77 | default_delete(const default_delete<_Up[]>&, |
78 | typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPTnoexcept {} |
79 | |
80 | template <class _Up> |
81 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
82 | typename _EnableIfConvertible<_Up>::type |
83 | operator()(_Up* __ptr) const _NOEXCEPTnoexcept { |
84 | static_assert(sizeof(_Tp) > 0, |
85 | "default_delete can not delete incomplete type"); |
86 | static_assert(!is_void<_Tp>::value, |
87 | "default_delete can not delete void type"); |
88 | delete[] __ptr; |
89 | } |
90 | }; |
91 | |
92 | template <class _Deleter> |
93 | struct __unique_ptr_deleter_sfinae { |
94 | static_assert(!is_reference<_Deleter>::value, "incorrect specialization"); |
95 | typedef const _Deleter& __lval_ref_type; |
96 | typedef _Deleter&& __good_rval_ref_type; |
97 | typedef true_type __enable_rval_overload; |
98 | }; |
99 | |
100 | template <class _Deleter> |
101 | struct __unique_ptr_deleter_sfinae<_Deleter const&> { |
102 | typedef const _Deleter& __lval_ref_type; |
103 | typedef const _Deleter&& __bad_rval_ref_type; |
104 | typedef false_type __enable_rval_overload; |
105 | }; |
106 | |
107 | template <class _Deleter> |
108 | struct __unique_ptr_deleter_sfinae<_Deleter&> { |
109 | typedef _Deleter& __lval_ref_type; |
110 | typedef _Deleter&& __bad_rval_ref_type; |
111 | typedef false_type __enable_rval_overload; |
112 | }; |
113 | |
114 | #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI) |
115 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) |
116 | #else |
117 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI |
118 | #endif |
119 | |
120 | template <class _Tp, class _Dp = default_delete<_Tp> > |
121 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) unique_ptr { |
122 | public: |
123 | typedef _Tp element_type; |
124 | typedef _Dp deleter_type; |
125 | typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) typename __pointer<_Tp, deleter_type>::type pointer; |
126 | |
127 | static_assert(!is_rvalue_reference<deleter_type>::value, |
128 | "the specified deleter type cannot be an rvalue reference"); |
129 | |
130 | private: |
131 | __compressed_pair<pointer, deleter_type> __ptr_; |
132 | |
133 | struct __nat { int __for_bool_; }; |
134 | |
135 | typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; |
136 | |
137 | template <bool _Dummy> |
138 | using _LValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
139 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; |
140 | |
141 | template <bool _Dummy> |
142 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
143 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; |
144 | |
145 | template <bool _Dummy> |
146 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
147 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; |
148 | |
149 | template <bool _Dummy, class _Deleter = typename __dependent_type< |
150 | __identity<deleter_type>, _Dummy>::type> |
151 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
152 | typename enable_if<is_default_constructible<_Deleter>::value && |
153 | !is_pointer<_Deleter>::value>::type; |
154 | |
155 | template <class _ArgType> |
156 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
157 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; |
158 | |
159 | template <class _UPtr, class _Up> |
160 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
161 | is_convertible<typename _UPtr::pointer, pointer>::value && |
162 | !is_array<_Up>::value |
163 | >::type; |
164 | |
165 | template <class _UDel> |
166 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
167 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || |
168 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) |
169 | >::type; |
170 | |
171 | template <class _UDel> |
172 | using _EnableIfDeleterAssignable = typename enable_if< |
173 | is_assignable<_Dp&, _UDel&&>::value |
174 | >::type; |
175 | |
176 | public: |
177 | template <bool _Dummy = true, |
178 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
179 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
180 | _LIBCPP_CONSTEXPRconstexpr unique_ptr() _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
181 | |
182 | template <bool _Dummy = true, |
183 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
184 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
185 | _LIBCPP_CONSTEXPRconstexpr unique_ptr(nullptr_t) _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
186 | |
187 | template <bool _Dummy = true, |
188 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
189 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
190 | explicit unique_ptr(pointer __p) _NOEXCEPTnoexcept : __ptr_(__p, __default_init_tag()) {} |
191 | |
192 | template <bool _Dummy = true, |
193 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > |
194 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
195 | unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
196 | : __ptr_(__p, __d) {} |
197 | |
198 | template <bool _Dummy = true, |
199 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > |
200 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
201 | unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
202 | : __ptr_(__p, _VSTDstd::__1::move(__d)) { |
203 | static_assert(!is_reference<deleter_type>::value, |
204 | "rvalue deleter bound to reference"); |
205 | } |
206 | |
207 | template <bool _Dummy = true, |
208 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > > |
209 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
210 | unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete; |
211 | |
212 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
213 | unique_ptr(unique_ptr&& __u) _NOEXCEPTnoexcept |
214 | : __ptr_(__u.release(), _VSTDstd::__1::forward<deleter_type>(__u.get_deleter())) { |
215 | } |
216 | |
217 | template <class _Up, class _Ep, |
218 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
219 | class = _EnableIfDeleterConvertible<_Ep> |
220 | > |
221 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
222 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept |
223 | : __ptr_(__u.release(), _VSTDstd::__1::forward<_Ep>(__u.get_deleter())) {} |
224 | |
225 | #if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
226 | template <class _Up> |
227 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
228 | unique_ptr(auto_ptr<_Up>&& __p, |
229 | typename enable_if<is_convertible<_Up*, _Tp*>::value && |
230 | is_same<_Dp, default_delete<_Tp> >::value, |
231 | __nat>::type = __nat()) _NOEXCEPTnoexcept |
232 | : __ptr_(__p.release(), __default_init_tag()) {} |
233 | #endif |
234 | |
235 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
236 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPTnoexcept { |
237 | reset(__u.release()); |
238 | __ptr_.second() = _VSTDstd::__1::forward<deleter_type>(__u.get_deleter()); |
239 | return *this; |
240 | } |
241 | |
242 | template <class _Up, class _Ep, |
243 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
244 | class = _EnableIfDeleterAssignable<_Ep> |
245 | > |
246 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
247 | unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept { |
248 | reset(__u.release()); |
249 | __ptr_.second() = _VSTDstd::__1::forward<_Ep>(__u.get_deleter()); |
250 | return *this; |
251 | } |
252 | |
253 | #if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
254 | template <class _Up> |
255 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
256 | typename enable_if<is_convertible<_Up*, _Tp*>::value && |
257 | is_same<_Dp, default_delete<_Tp> >::value, |
258 | unique_ptr&>::type |
259 | operator=(auto_ptr<_Up> __p) { |
260 | reset(__p.release()); |
261 | return *this; |
262 | } |
263 | #endif |
264 | |
265 | #ifdef _LIBCPP_CXX03_LANG |
266 | unique_ptr(unique_ptr const&) = delete; |
267 | unique_ptr& operator=(unique_ptr const&) = delete; |
268 | #endif |
269 | |
270 | |
271 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
272 | ~unique_ptr() { reset(); } |
273 | |
274 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
275 | unique_ptr& operator=(nullptr_t) _NOEXCEPTnoexcept { |
276 | reset(); |
277 | return *this; |
278 | } |
279 | |
280 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
281 | typename add_lvalue_reference<_Tp>::type |
282 | operator*() const { |
283 | return *__ptr_.first(); |
284 | } |
285 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
286 | pointer operator->() const _NOEXCEPTnoexcept { |
287 | return __ptr_.first(); |
288 | } |
289 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
290 | pointer get() const _NOEXCEPTnoexcept { |
291 | return __ptr_.first(); |
292 | } |
293 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
294 | deleter_type& get_deleter() _NOEXCEPTnoexcept { |
295 | return __ptr_.second(); |
296 | } |
297 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
298 | const deleter_type& get_deleter() const _NOEXCEPTnoexcept { |
299 | return __ptr_.second(); |
300 | } |
301 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
302 | explicit operator bool() const _NOEXCEPTnoexcept { |
303 | return __ptr_.first() != nullptr; |
304 | } |
305 | |
306 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
307 | pointer release() _NOEXCEPTnoexcept { |
308 | pointer __t = __ptr_.first(); |
309 | __ptr_.first() = pointer(); |
310 | return __t; |
311 | } |
312 | |
313 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
314 | void reset(pointer __p = pointer()) _NOEXCEPTnoexcept { |
315 | pointer __tmp = __ptr_.first(); |
316 | __ptr_.first() = __p; |
317 | if (__tmp) |
318 | __ptr_.second()(__tmp); |
319 | } |
320 | |
321 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
322 | void swap(unique_ptr& __u) _NOEXCEPTnoexcept { |
323 | __ptr_.swap(__u.__ptr_); |
324 | } |
325 | }; |
326 | |
327 | |
328 | template <class _Tp, class _Dp> |
329 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) unique_ptr<_Tp[], _Dp> { |
330 | public: |
331 | typedef _Tp element_type; |
332 | typedef _Dp deleter_type; |
333 | typedef typename __pointer<_Tp, deleter_type>::type pointer; |
334 | |
335 | private: |
336 | __compressed_pair<pointer, deleter_type> __ptr_; |
337 | |
338 | template <class _From> |
339 | struct _CheckArrayPointerConversion : is_same<_From, pointer> {}; |
340 | |
341 | template <class _FromElem> |
342 | struct _CheckArrayPointerConversion<_FromElem*> |
343 | : integral_constant<bool, |
344 | is_same<_FromElem*, pointer>::value || |
345 | (is_same<pointer, element_type*>::value && |
346 | is_convertible<_FromElem(*)[], element_type(*)[]>::value) |
347 | > |
348 | {}; |
349 | |
350 | typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; |
351 | |
352 | template <bool _Dummy> |
353 | using _LValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
354 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; |
355 | |
356 | template <bool _Dummy> |
357 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
358 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; |
359 | |
360 | template <bool _Dummy> |
361 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
362 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; |
363 | |
364 | template <bool _Dummy, class _Deleter = typename __dependent_type< |
365 | __identity<deleter_type>, _Dummy>::type> |
366 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
367 | typename enable_if<is_default_constructible<_Deleter>::value && |
368 | !is_pointer<_Deleter>::value>::type; |
369 | |
370 | template <class _ArgType> |
371 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
372 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; |
373 | |
374 | template <class _Pp> |
375 | using _EnableIfPointerConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
376 | _CheckArrayPointerConversion<_Pp>::value |
377 | >::type; |
378 | |
379 | template <class _UPtr, class _Up, |
380 | class _ElemT = typename _UPtr::element_type> |
381 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
382 | is_array<_Up>::value && |
383 | is_same<pointer, element_type*>::value && |
384 | is_same<typename _UPtr::pointer, _ElemT*>::value && |
385 | is_convertible<_ElemT(*)[], element_type(*)[]>::value |
386 | >::type; |
387 | |
388 | template <class _UDel> |
389 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
390 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || |
391 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) |
392 | >::type; |
393 | |
394 | template <class _UDel> |
395 | using _EnableIfDeleterAssignable _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
396 | is_assignable<_Dp&, _UDel&&>::value |
397 | >::type; |
398 | |
399 | public: |
400 | template <bool _Dummy = true, |
401 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
402 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
403 | _LIBCPP_CONSTEXPRconstexpr unique_ptr() _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
404 | |
405 | template <bool _Dummy = true, |
406 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
407 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
408 | _LIBCPP_CONSTEXPRconstexpr unique_ptr(nullptr_t) _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
409 | |
410 | template <class _Pp, bool _Dummy = true, |
411 | class = _EnableIfDeleterDefaultConstructible<_Dummy>, |
412 | class = _EnableIfPointerConvertible<_Pp> > |
413 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
414 | explicit unique_ptr(_Pp __p) _NOEXCEPTnoexcept |
415 | : __ptr_(__p, __default_init_tag()) {} |
416 | |
417 | template <class _Pp, bool _Dummy = true, |
418 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >, |
419 | class = _EnableIfPointerConvertible<_Pp> > |
420 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
421 | unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
422 | : __ptr_(__p, __d) {} |
423 | |
424 | template <bool _Dummy = true, |
425 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > |
426 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
427 | unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
428 | : __ptr_(nullptr, __d) {} |
429 | |
430 | template <class _Pp, bool _Dummy = true, |
431 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >, |
432 | class = _EnableIfPointerConvertible<_Pp> > |
433 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
434 | unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
435 | : __ptr_(__p, _VSTDstd::__1::move(__d)) { |
436 | static_assert(!is_reference<deleter_type>::value, |
437 | "rvalue deleter bound to reference"); |
438 | } |
439 | |
440 | template <bool _Dummy = true, |
441 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > |
442 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
443 | unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
444 | : __ptr_(nullptr, _VSTDstd::__1::move(__d)) { |
445 | static_assert(!is_reference<deleter_type>::value, |
446 | "rvalue deleter bound to reference"); |
447 | } |
448 | |
449 | template <class _Pp, bool _Dummy = true, |
450 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >, |
451 | class = _EnableIfPointerConvertible<_Pp> > |
452 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
453 | unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete; |
454 | |
455 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
456 | unique_ptr(unique_ptr&& __u) _NOEXCEPTnoexcept |
457 | : __ptr_(__u.release(), _VSTDstd::__1::forward<deleter_type>(__u.get_deleter())) { |
458 | } |
459 | |
460 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
461 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPTnoexcept { |
462 | reset(__u.release()); |
463 | __ptr_.second() = _VSTDstd::__1::forward<deleter_type>(__u.get_deleter()); |
464 | return *this; |
465 | } |
466 | |
467 | template <class _Up, class _Ep, |
468 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
469 | class = _EnableIfDeleterConvertible<_Ep> |
470 | > |
471 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
472 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept |
473 | : __ptr_(__u.release(), _VSTDstd::__1::forward<_Ep>(__u.get_deleter())) { |
474 | } |
475 | |
476 | template <class _Up, class _Ep, |
477 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
478 | class = _EnableIfDeleterAssignable<_Ep> |
479 | > |
480 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
481 | unique_ptr& |
482 | operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept { |
483 | reset(__u.release()); |
484 | __ptr_.second() = _VSTDstd::__1::forward<_Ep>(__u.get_deleter()); |
485 | return *this; |
486 | } |
487 | |
488 | #ifdef _LIBCPP_CXX03_LANG |
489 | unique_ptr(unique_ptr const&) = delete; |
490 | unique_ptr& operator=(unique_ptr const&) = delete; |
491 | #endif |
492 | |
493 | public: |
494 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
495 | ~unique_ptr() { reset(); } |
496 | |
497 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
498 | unique_ptr& operator=(nullptr_t) _NOEXCEPTnoexcept { |
499 | reset(); |
500 | return *this; |
501 | } |
502 | |
503 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
504 | typename add_lvalue_reference<_Tp>::type |
505 | operator[](size_t __i) const { |
506 | return __ptr_.first()[__i]; |
507 | } |
508 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
509 | pointer get() const _NOEXCEPTnoexcept { |
510 | return __ptr_.first(); |
511 | } |
512 | |
513 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
514 | deleter_type& get_deleter() _NOEXCEPTnoexcept { |
515 | return __ptr_.second(); |
516 | } |
517 | |
518 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
519 | const deleter_type& get_deleter() const _NOEXCEPTnoexcept { |
520 | return __ptr_.second(); |
521 | } |
522 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
523 | explicit operator bool() const _NOEXCEPTnoexcept { |
524 | return __ptr_.first() != nullptr; |
525 | } |
526 | |
527 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
528 | pointer release() _NOEXCEPTnoexcept { |
529 | pointer __t = __ptr_.first(); |
530 | __ptr_.first() = pointer(); |
531 | return __t; |
532 | } |
533 | |
534 | template <class _Pp> |
535 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
536 | typename enable_if< |
537 | _CheckArrayPointerConversion<_Pp>::value |
538 | >::type |
539 | reset(_Pp __p) _NOEXCEPTnoexcept { |
540 | pointer __tmp = __ptr_.first(); |
541 | __ptr_.first() = __p; |
542 | if (__tmp) |
543 | __ptr_.second()(__tmp); |
544 | } |
545 | |
546 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
547 | void reset(nullptr_t = nullptr) _NOEXCEPTnoexcept { |
548 | pointer __tmp = __ptr_.first(); |
549 | __ptr_.first() = nullptr; |
550 | if (__tmp) |
551 | __ptr_.second()(__tmp); |
552 | } |
553 | |
554 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
555 | void swap(unique_ptr& __u) _NOEXCEPTnoexcept { |
556 | __ptr_.swap(__u.__ptr_); |
557 | } |
558 | |
559 | }; |
560 | |
561 | template <class _Tp, class _Dp> |
562 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
563 | typename enable_if< |
564 | __is_swappable<_Dp>::value, |
565 | void |
566 | >::type |
567 | swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPTnoexcept {__x.swap(__y);} |
568 | |
569 | template <class _T1, class _D1, class _T2, class _D2> |
570 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
571 | bool |
572 | operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() == __y.get();} |
573 | |
574 | template <class _T1, class _D1, class _T2, class _D2> |
575 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
576 | bool |
577 | operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x == __y);} |
578 | |
579 | template <class _T1, class _D1, class _T2, class _D2> |
580 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
581 | bool |
582 | operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) |
583 | { |
584 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
585 | typedef typename unique_ptr<_T2, _D2>::pointer _P2; |
586 | typedef typename common_type<_P1, _P2>::type _Vp; |
587 | return less<_Vp>()(__x.get(), __y.get()); |
588 | } |
589 | |
590 | template <class _T1, class _D1, class _T2, class _D2> |
591 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
592 | bool |
593 | operator> (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __y < __x;} |
594 | |
595 | template <class _T1, class _D1, class _T2, class _D2> |
596 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
597 | bool |
598 | operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__y < __x);} |
599 | |
600 | template <class _T1, class _D1, class _T2, class _D2> |
601 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
602 | bool |
603 | operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} |
604 | |
605 | template <class _T1, class _D1> |
606 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
607 | bool |
608 | operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPTnoexcept |
609 | { |
610 | return !__x; |
611 | } |
612 | |
613 | template <class _T1, class _D1> |
614 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
615 | bool |
616 | operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPTnoexcept |
617 | { |
618 | return !__x; |
619 | } |
620 | |
621 | template <class _T1, class _D1> |
622 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
623 | bool |
624 | operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPTnoexcept |
625 | { |
626 | return static_cast<bool>(__x); |
627 | } |
628 | |
629 | template <class _T1, class _D1> |
630 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
631 | bool |
632 | operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPTnoexcept |
633 | { |
634 | return static_cast<bool>(__x); |
635 | } |
636 | |
637 | template <class _T1, class _D1> |
638 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
639 | bool |
640 | operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
641 | { |
642 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
643 | return less<_P1>()(__x.get(), nullptr); |
644 | } |
645 | |
646 | template <class _T1, class _D1> |
647 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
648 | bool |
649 | operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
650 | { |
651 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
652 | return less<_P1>()(nullptr, __x.get()); |
653 | } |
654 | |
655 | template <class _T1, class _D1> |
656 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
657 | bool |
658 | operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
659 | { |
660 | return nullptr < __x; |
661 | } |
662 | |
663 | template <class _T1, class _D1> |
664 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
665 | bool |
666 | operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
667 | { |
668 | return __x < nullptr; |
669 | } |
670 | |
671 | template <class _T1, class _D1> |
672 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
673 | bool |
674 | operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
675 | { |
676 | return !(nullptr < __x); |
677 | } |
678 | |
679 | template <class _T1, class _D1> |
680 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
681 | bool |
682 | operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
683 | { |
684 | return !(__x < nullptr); |
685 | } |
686 | |
687 | template <class _T1, class _D1> |
688 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
689 | bool |
690 | operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
691 | { |
692 | return !(__x < nullptr); |
693 | } |
694 | |
695 | template <class _T1, class _D1> |
696 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
697 | bool |
698 | operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
699 | { |
700 | return !(nullptr < __x); |
701 | } |
702 | |
703 | #if _LIBCPP_STD_VER14 > 11 |
704 | |
705 | template<class _Tp> |
706 | struct __unique_if |
707 | { |
708 | typedef unique_ptr<_Tp> __unique_single; |
709 | }; |
710 | |
711 | template<class _Tp> |
712 | struct __unique_if<_Tp[]> |
713 | { |
714 | typedef unique_ptr<_Tp[]> __unique_array_unknown_bound; |
715 | }; |
716 | |
717 | template<class _Tp, size_t _Np> |
718 | struct __unique_if<_Tp[_Np]> |
719 | { |
720 | typedef void __unique_array_known_bound; |
721 | }; |
722 | |
723 | template<class _Tp, class... _Args> |
724 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
725 | typename __unique_if<_Tp>::__unique_single |
726 | make_unique(_Args&&... __args) |
727 | { |
728 | return unique_ptr<_Tp>(new _Tp(_VSTDstd::__1::forward<_Args>(__args)...)); |
729 | } |
730 | |
731 | template<class _Tp> |
732 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
733 | typename __unique_if<_Tp>::__unique_array_unknown_bound |
734 | make_unique(size_t __n) |
735 | { |
736 | typedef typename remove_extent<_Tp>::type _Up; |
737 | return unique_ptr<_Tp>(new _Up[__n]()); |
738 | } |
739 | |
740 | template<class _Tp, class... _Args> |
741 | typename __unique_if<_Tp>::__unique_array_known_bound |
742 | make_unique(_Args&&...) = delete; |
743 | |
744 | #endif // _LIBCPP_STD_VER > 11 |
745 | |
746 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash; |
747 | |
748 | template <class _Tp, class _Dp> |
749 | #ifdef _LIBCPP_CXX03_LANG |
750 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash<unique_ptr<_Tp, _Dp> > |
751 | #else |
752 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash<__enable_hash_helper< |
753 | unique_ptr<_Tp, _Dp>, typename unique_ptr<_Tp, _Dp>::pointer> > |
754 | #endif |
755 | { |
756 | #if _LIBCPP_STD_VER14 <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) |
757 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unique_ptr<_Tp, _Dp> argument_type; |
758 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; |
759 | #endif |
760 | |
761 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
762 | size_t operator()(const unique_ptr<_Tp, _Dp>& __ptr) const |
763 | { |
764 | typedef typename unique_ptr<_Tp, _Dp>::pointer pointer; |
765 | return hash<pointer>()(__ptr.get()); |
766 | } |
767 | }; |
768 | |
769 | _LIBCPP_END_NAMESPACE_STD} } |
770 | |
771 | _LIBCPP_POP_MACROSpop_macro("min") pop_macro("max") |
772 | |
773 | #endif // _LIBCPP___MEMORY_UNIQUE_PTR_H |