1dda28197Spatrick //===-- DWARFASTParserClang.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9be691f3bSpatrick #include <cstdlib>
10061da546Spatrick
11*f6aab3d8Srobert #include "DWARFASTParser.h"
12061da546Spatrick #include "DWARFASTParserClang.h"
13061da546Spatrick #include "DWARFDebugInfo.h"
14061da546Spatrick #include "DWARFDeclContext.h"
15061da546Spatrick #include "DWARFDefines.h"
16061da546Spatrick #include "SymbolFileDWARF.h"
17061da546Spatrick #include "SymbolFileDWARFDebugMap.h"
18dda28197Spatrick #include "SymbolFileDWARFDwo.h"
19061da546Spatrick #include "UniqueDWARFASTType.h"
20061da546Spatrick
21dda28197Spatrick #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
22dda28197Spatrick #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
23dda28197Spatrick #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
24061da546Spatrick #include "Plugins/Language/ObjC/ObjCLanguage.h"
25061da546Spatrick #include "lldb/Core/Module.h"
26061da546Spatrick #include "lldb/Core/Value.h"
27061da546Spatrick #include "lldb/Host/Host.h"
28061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
29061da546Spatrick #include "lldb/Symbol/Function.h"
30061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
31061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
32061da546Spatrick #include "lldb/Symbol/TypeList.h"
33061da546Spatrick #include "lldb/Symbol/TypeMap.h"
34061da546Spatrick #include "lldb/Target/Language.h"
35061da546Spatrick #include "lldb/Utility/LLDBAssert.h"
36061da546Spatrick #include "lldb/Utility/Log.h"
37061da546Spatrick #include "lldb/Utility/StreamString.h"
38061da546Spatrick
39061da546Spatrick #include "clang/AST/CXXInheritance.h"
40061da546Spatrick #include "clang/AST/DeclCXX.h"
41061da546Spatrick #include "clang/AST/DeclObjC.h"
42061da546Spatrick #include "clang/AST/DeclTemplate.h"
43*f6aab3d8Srobert #include "clang/AST/Type.h"
44*f6aab3d8Srobert #include "llvm/Demangle/Demangle.h"
45061da546Spatrick
46061da546Spatrick #include <map>
47061da546Spatrick #include <memory>
48*f6aab3d8Srobert #include <optional>
49061da546Spatrick #include <vector>
50061da546Spatrick
51061da546Spatrick //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
52061da546Spatrick
53061da546Spatrick #ifdef ENABLE_DEBUG_PRINTF
54be691f3bSpatrick #include <cstdio>
55061da546Spatrick #define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
56061da546Spatrick #else
57061da546Spatrick #define DEBUG_PRINTF(fmt, ...)
58061da546Spatrick #endif
59061da546Spatrick
60061da546Spatrick using namespace lldb;
61061da546Spatrick using namespace lldb_private;
62*f6aab3d8Srobert using namespace lldb_private::dwarf;
DWARFASTParserClang(TypeSystemClang & ast)63dda28197Spatrick DWARFASTParserClang::DWARFASTParserClang(TypeSystemClang &ast)
64061da546Spatrick : m_ast(ast), m_die_to_decl_ctx(), m_decl_ctx_to_die() {}
65061da546Spatrick
66be691f3bSpatrick DWARFASTParserClang::~DWARFASTParserClang() = default;
67061da546Spatrick
DeclKindIsCXXClass(clang::Decl::Kind decl_kind)68061da546Spatrick static bool DeclKindIsCXXClass(clang::Decl::Kind decl_kind) {
69061da546Spatrick switch (decl_kind) {
70061da546Spatrick case clang::Decl::CXXRecord:
71061da546Spatrick case clang::Decl::ClassTemplateSpecialization:
72061da546Spatrick return true;
73061da546Spatrick default:
74061da546Spatrick break;
75061da546Spatrick }
76061da546Spatrick return false;
77061da546Spatrick }
78061da546Spatrick
79061da546Spatrick
GetClangASTImporter()80061da546Spatrick ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() {
81061da546Spatrick if (!m_clang_ast_importer_up) {
82dda28197Spatrick m_clang_ast_importer_up = std::make_unique<ClangASTImporter>();
83061da546Spatrick }
84061da546Spatrick return *m_clang_ast_importer_up;
85061da546Spatrick }
86061da546Spatrick
87061da546Spatrick /// Detect a forward declaration that is nested in a DW_TAG_module.
IsClangModuleFwdDecl(const DWARFDIE & Die)88061da546Spatrick static bool IsClangModuleFwdDecl(const DWARFDIE &Die) {
89061da546Spatrick if (!Die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
90061da546Spatrick return false;
91061da546Spatrick auto Parent = Die.GetParent();
92061da546Spatrick while (Parent.IsValid()) {
93061da546Spatrick if (Parent.Tag() == DW_TAG_module)
94061da546Spatrick return true;
95061da546Spatrick Parent = Parent.GetParent();
96061da546Spatrick }
97061da546Spatrick return false;
98061da546Spatrick }
99061da546Spatrick
GetContainingClangModuleDIE(const DWARFDIE & die)100061da546Spatrick static DWARFDIE GetContainingClangModuleDIE(const DWARFDIE &die) {
101061da546Spatrick if (die.IsValid()) {
102061da546Spatrick DWARFDIE top_module_die;
103061da546Spatrick // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
104061da546Spatrick // if so
105061da546Spatrick for (DWARFDIE parent = die.GetParent(); parent.IsValid();
106061da546Spatrick parent = parent.GetParent()) {
107061da546Spatrick const dw_tag_t tag = parent.Tag();
108061da546Spatrick if (tag == DW_TAG_module)
109061da546Spatrick top_module_die = parent;
110061da546Spatrick else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
111061da546Spatrick break;
112061da546Spatrick }
113061da546Spatrick
114061da546Spatrick return top_module_die;
115061da546Spatrick }
116061da546Spatrick return DWARFDIE();
117061da546Spatrick }
118061da546Spatrick
GetContainingClangModule(const DWARFDIE & die)119061da546Spatrick static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
120061da546Spatrick if (die.IsValid()) {
121061da546Spatrick DWARFDIE clang_module_die = GetContainingClangModuleDIE(die);
122061da546Spatrick
123061da546Spatrick if (clang_module_die) {
124061da546Spatrick const char *module_name = clang_module_die.GetName();
125061da546Spatrick if (module_name)
126061da546Spatrick return die.GetDWARF()->GetExternalModule(
127061da546Spatrick lldb_private::ConstString(module_name));
128061da546Spatrick }
129061da546Spatrick }
130061da546Spatrick return lldb::ModuleSP();
131061da546Spatrick }
132061da546Spatrick
ParseTypeFromClangModule(const SymbolContext & sc,const DWARFDIE & die,Log * log)133061da546Spatrick TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
134061da546Spatrick const DWARFDIE &die,
135061da546Spatrick Log *log) {
136061da546Spatrick ModuleSP clang_module_sp = GetContainingClangModule(die);
137061da546Spatrick if (!clang_module_sp)
138061da546Spatrick return TypeSP();
139061da546Spatrick
140061da546Spatrick // If this type comes from a Clang module, recursively look in the
141061da546Spatrick // DWARF section of the .pcm file in the module cache. Clang
142061da546Spatrick // generates DWO skeleton units as breadcrumbs to find them.
143061da546Spatrick llvm::SmallVector<CompilerContext, 4> decl_context;
144061da546Spatrick die.GetDeclContext(decl_context);
145061da546Spatrick TypeMap pcm_types;
146061da546Spatrick
147061da546Spatrick // The type in the Clang module must have the same language as the current CU.
148061da546Spatrick LanguageSet languages;
149be691f3bSpatrick languages.Insert(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()));
150061da546Spatrick llvm::DenseSet<SymbolFile *> searched_symbol_files;
151061da546Spatrick clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
152061da546Spatrick searched_symbol_files, pcm_types);
153061da546Spatrick if (pcm_types.Empty()) {
154061da546Spatrick // Since this type is defined in one of the Clang modules imported
155061da546Spatrick // by this symbol file, search all of them. Instead of calling
156061da546Spatrick // sym_file->FindTypes(), which would return this again, go straight
157061da546Spatrick // to the imported modules.
158061da546Spatrick auto &sym_file = die.GetCU()->GetSymbolFileDWARF();
159061da546Spatrick
160061da546Spatrick // Well-formed clang modules never form cycles; guard against corrupted
161061da546Spatrick // ones by inserting the current file.
162061da546Spatrick searched_symbol_files.insert(&sym_file);
163061da546Spatrick sym_file.ForEachExternalModule(
164061da546Spatrick *sc.comp_unit, searched_symbol_files, [&](Module &module) {
165061da546Spatrick module.GetSymbolFile()->FindTypes(decl_context, languages,
166061da546Spatrick searched_symbol_files, pcm_types);
167061da546Spatrick return pcm_types.GetSize();
168061da546Spatrick });
169061da546Spatrick }
170061da546Spatrick
171061da546Spatrick if (!pcm_types.GetSize())
172061da546Spatrick return TypeSP();
173061da546Spatrick
174061da546Spatrick // We found a real definition for this type in the Clang module, so lets use
175061da546Spatrick // it and cache the fact that we found a complete type for this die.
176061da546Spatrick TypeSP pcm_type_sp = pcm_types.GetTypeAtIndex(0);
177061da546Spatrick if (!pcm_type_sp)
178061da546Spatrick return TypeSP();
179061da546Spatrick
180061da546Spatrick lldb_private::CompilerType pcm_type = pcm_type_sp->GetForwardCompilerType();
181061da546Spatrick lldb_private::CompilerType type =
182061da546Spatrick GetClangASTImporter().CopyType(m_ast, pcm_type);
183061da546Spatrick
184061da546Spatrick if (!type)
185061da546Spatrick return TypeSP();
186061da546Spatrick
187061da546Spatrick // Under normal operation pcm_type is a shallow forward declaration
188061da546Spatrick // that gets completed later. This is necessary to support cyclic
189061da546Spatrick // data structures. If, however, pcm_type is already complete (for
190061da546Spatrick // example, because it was loaded for a different target before),
191061da546Spatrick // the definition needs to be imported right away, too.
192061da546Spatrick // Type::ResolveClangType() effectively ignores the ResolveState
193061da546Spatrick // inside type_sp and only looks at IsDefined(), so it never calls
194061da546Spatrick // ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(),
195061da546Spatrick // which does extra work for Objective-C classes. This would result
196061da546Spatrick // in only the forward declaration to be visible.
197061da546Spatrick if (pcm_type.IsDefined())
198061da546Spatrick GetClangASTImporter().RequireCompleteType(ClangUtil::GetQualType(type));
199061da546Spatrick
200061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
201*f6aab3d8Srobert auto type_sp = dwarf->MakeType(
202*f6aab3d8Srobert die.GetID(), pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(nullptr),
203*f6aab3d8Srobert nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid,
204*f6aab3d8Srobert &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward,
205*f6aab3d8Srobert TypePayloadClang(GetOwningClangModule(die)));
206061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
207dda28197Spatrick clang::TagDecl *tag_decl = TypeSystemClang::GetAsTagDecl(type);
208dda28197Spatrick if (tag_decl) {
209061da546Spatrick LinkDeclContextToDIE(tag_decl, die);
210dda28197Spatrick } else {
211061da546Spatrick clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
212061da546Spatrick if (defn_decl_ctx)
213061da546Spatrick LinkDeclContextToDIE(defn_decl_ctx, die);
214061da546Spatrick }
215061da546Spatrick
216061da546Spatrick return type_sp;
217061da546Spatrick }
218061da546Spatrick
ForcefullyCompleteType(CompilerType type)219be691f3bSpatrick static void ForcefullyCompleteType(CompilerType type) {
220be691f3bSpatrick bool started = TypeSystemClang::StartTagDeclarationDefinition(type);
221be691f3bSpatrick lldbassert(started && "Unable to start a class type definition.");
222be691f3bSpatrick TypeSystemClang::CompleteTagDeclarationDefinition(type);
223be691f3bSpatrick const clang::TagDecl *td = ClangUtil::GetAsTagDecl(type);
224*f6aab3d8Srobert auto ts_sp = type.GetTypeSystem();
225*f6aab3d8Srobert auto ts = ts_sp.dyn_cast_or_null<TypeSystemClang>();
226*f6aab3d8Srobert if (ts)
227*f6aab3d8Srobert ts->SetDeclIsForcefullyCompleted(td);
228be691f3bSpatrick }
229be691f3bSpatrick
230be691f3bSpatrick /// This function serves a similar purpose as RequireCompleteType above, but it
231be691f3bSpatrick /// avoids completing the type if it is not immediately necessary. It only
232be691f3bSpatrick /// ensures we _can_ complete the type later.
PrepareContextToReceiveMembers(TypeSystemClang & ast,ClangASTImporter & ast_importer,clang::DeclContext * decl_ctx,DWARFDIE die,const char * type_name_cstr)233be691f3bSpatrick static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
234061da546Spatrick ClangASTImporter &ast_importer,
235061da546Spatrick clang::DeclContext *decl_ctx,
236061da546Spatrick DWARFDIE die,
237061da546Spatrick const char *type_name_cstr) {
238061da546Spatrick auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
239061da546Spatrick if (!tag_decl_ctx)
240be691f3bSpatrick return; // Non-tag context are always ready.
241be691f3bSpatrick
242be691f3bSpatrick // We have already completed the type, or we have found its definition and are
243be691f3bSpatrick // ready to complete it later (cf. ParseStructureLikeDIE).
244be691f3bSpatrick if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
245061da546Spatrick return;
246061da546Spatrick
247be691f3bSpatrick // We reach this point of the tag was present in the debug info as a
248be691f3bSpatrick // declaration only. If it was imported from another AST context (in the
249be691f3bSpatrick // gmodules case), we can complete the type by doing a full import.
250be691f3bSpatrick
251061da546Spatrick // If this type was not imported from an external AST, there's nothing to do.
252061da546Spatrick CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
253be691f3bSpatrick if (type && ast_importer.CanImport(type)) {
254061da546Spatrick auto qual_type = ClangUtil::GetQualType(type);
255be691f3bSpatrick if (ast_importer.RequireCompleteType(qual_type))
256be691f3bSpatrick return;
257061da546Spatrick die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(
258*f6aab3d8Srobert "Unable to complete the Decl context for DIE {0} at offset "
259*f6aab3d8Srobert "{1:x16}.\nPlease file a bug report.",
260061da546Spatrick type_name_cstr ? type_name_cstr : "", die.GetOffset());
261061da546Spatrick }
262be691f3bSpatrick
263be691f3bSpatrick // We don't have a type definition and/or the import failed. We must
264be691f3bSpatrick // forcefully complete the type to avoid crashes.
265be691f3bSpatrick ForcefullyCompleteType(type);
266061da546Spatrick }
267061da546Spatrick
ParsedDWARFTypeAttributes(const DWARFDIE & die)268061da546Spatrick ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
269061da546Spatrick DWARFAttributes attributes;
270061da546Spatrick size_t num_attributes = die.GetAttributes(attributes);
271061da546Spatrick for (size_t i = 0; i < num_attributes; ++i) {
272061da546Spatrick dw_attr_t attr = attributes.AttributeAtIndex(i);
273061da546Spatrick DWARFFormValue form_value;
274061da546Spatrick if (!attributes.ExtractFormValueAtIndex(i, form_value))
275061da546Spatrick continue;
276061da546Spatrick switch (attr) {
277061da546Spatrick case DW_AT_abstract_origin:
278061da546Spatrick abstract_origin = form_value;
279061da546Spatrick break;
280061da546Spatrick
281061da546Spatrick case DW_AT_accessibility:
282*f6aab3d8Srobert accessibility = DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned());
283061da546Spatrick break;
284061da546Spatrick
285061da546Spatrick case DW_AT_artificial:
286061da546Spatrick is_artificial = form_value.Boolean();
287061da546Spatrick break;
288061da546Spatrick
289061da546Spatrick case DW_AT_bit_stride:
290061da546Spatrick bit_stride = form_value.Unsigned();
291061da546Spatrick break;
292061da546Spatrick
293061da546Spatrick case DW_AT_byte_size:
294061da546Spatrick byte_size = form_value.Unsigned();
295061da546Spatrick break;
296061da546Spatrick
297061da546Spatrick case DW_AT_byte_stride:
298061da546Spatrick byte_stride = form_value.Unsigned();
299061da546Spatrick break;
300061da546Spatrick
301061da546Spatrick case DW_AT_calling_convention:
302061da546Spatrick calling_convention = form_value.Unsigned();
303061da546Spatrick break;
304061da546Spatrick
305061da546Spatrick case DW_AT_containing_type:
306061da546Spatrick containing_type = form_value;
307061da546Spatrick break;
308061da546Spatrick
309061da546Spatrick case DW_AT_decl_file:
310be691f3bSpatrick // die.GetCU() can differ if DW_AT_specification uses DW_FORM_ref_addr.
311be691f3bSpatrick decl.SetFile(
312be691f3bSpatrick attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));
313061da546Spatrick break;
314061da546Spatrick case DW_AT_decl_line:
315061da546Spatrick decl.SetLine(form_value.Unsigned());
316061da546Spatrick break;
317061da546Spatrick case DW_AT_decl_column:
318061da546Spatrick decl.SetColumn(form_value.Unsigned());
319061da546Spatrick break;
320061da546Spatrick
321061da546Spatrick case DW_AT_declaration:
322061da546Spatrick is_forward_declaration = form_value.Boolean();
323061da546Spatrick break;
324061da546Spatrick
325061da546Spatrick case DW_AT_encoding:
326061da546Spatrick encoding = form_value.Unsigned();
327061da546Spatrick break;
328061da546Spatrick
329061da546Spatrick case DW_AT_enum_class:
330061da546Spatrick is_scoped_enum = form_value.Boolean();
331061da546Spatrick break;
332061da546Spatrick
333061da546Spatrick case DW_AT_explicit:
334061da546Spatrick is_explicit = form_value.Boolean();
335061da546Spatrick break;
336061da546Spatrick
337061da546Spatrick case DW_AT_external:
338061da546Spatrick if (form_value.Unsigned())
339061da546Spatrick storage = clang::SC_Extern;
340061da546Spatrick break;
341061da546Spatrick
342061da546Spatrick case DW_AT_inline:
343061da546Spatrick is_inline = form_value.Boolean();
344061da546Spatrick break;
345061da546Spatrick
346061da546Spatrick case DW_AT_linkage_name:
347061da546Spatrick case DW_AT_MIPS_linkage_name:
348061da546Spatrick mangled_name = form_value.AsCString();
349061da546Spatrick break;
350061da546Spatrick
351061da546Spatrick case DW_AT_name:
352061da546Spatrick name.SetCString(form_value.AsCString());
353061da546Spatrick break;
354061da546Spatrick
355061da546Spatrick case DW_AT_object_pointer:
356061da546Spatrick object_pointer = form_value.Reference();
357061da546Spatrick break;
358061da546Spatrick
359061da546Spatrick case DW_AT_signature:
360061da546Spatrick signature = form_value;
361061da546Spatrick break;
362061da546Spatrick
363061da546Spatrick case DW_AT_specification:
364061da546Spatrick specification = form_value;
365061da546Spatrick break;
366061da546Spatrick
367061da546Spatrick case DW_AT_type:
368061da546Spatrick type = form_value;
369061da546Spatrick break;
370061da546Spatrick
371061da546Spatrick case DW_AT_virtuality:
372061da546Spatrick is_virtual = form_value.Boolean();
373061da546Spatrick break;
374061da546Spatrick
375061da546Spatrick case DW_AT_APPLE_objc_complete_type:
376061da546Spatrick is_complete_objc_class = form_value.Signed();
377061da546Spatrick break;
378061da546Spatrick
379061da546Spatrick case DW_AT_APPLE_objc_direct:
380061da546Spatrick is_objc_direct_call = true;
381061da546Spatrick break;
382061da546Spatrick
383061da546Spatrick case DW_AT_APPLE_runtime_class:
384061da546Spatrick class_language = (LanguageType)form_value.Signed();
385061da546Spatrick break;
386061da546Spatrick
387061da546Spatrick case DW_AT_GNU_vector:
388061da546Spatrick is_vector = form_value.Boolean();
389061da546Spatrick break;
390061da546Spatrick case DW_AT_export_symbols:
391061da546Spatrick exports_symbols = form_value.Boolean();
392061da546Spatrick break;
393*f6aab3d8Srobert case DW_AT_rvalue_reference:
394*f6aab3d8Srobert ref_qual = clang::RQ_RValue;
395*f6aab3d8Srobert break;
396*f6aab3d8Srobert case DW_AT_reference:
397*f6aab3d8Srobert ref_qual = clang::RQ_LValue;
398*f6aab3d8Srobert break;
399061da546Spatrick }
400061da546Spatrick }
401061da546Spatrick }
402061da546Spatrick
GetUnitName(const DWARFDIE & die)403061da546Spatrick static std::string GetUnitName(const DWARFDIE &die) {
404061da546Spatrick if (DWARFUnit *unit = die.GetCU())
405061da546Spatrick return unit->GetAbsolutePath().GetPath();
406061da546Spatrick return "<missing DWARF unit path>";
407061da546Spatrick }
408061da546Spatrick
ParseTypeFromDWARF(const SymbolContext & sc,const DWARFDIE & die,bool * type_is_new_ptr)409061da546Spatrick TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
410061da546Spatrick const DWARFDIE &die,
411061da546Spatrick bool *type_is_new_ptr) {
412061da546Spatrick if (type_is_new_ptr)
413061da546Spatrick *type_is_new_ptr = false;
414061da546Spatrick
415061da546Spatrick if (!die)
416061da546Spatrick return nullptr;
417061da546Spatrick
418*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
419061da546Spatrick
420061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
421061da546Spatrick if (log) {
422061da546Spatrick DWARFDIE context_die;
423061da546Spatrick clang::DeclContext *context =
424061da546Spatrick GetClangDeclContextContainingDIE(die, &context_die);
425061da546Spatrick
426061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
427061da546Spatrick log,
428061da546Spatrick "DWARFASTParserClang::ParseTypeFromDWARF "
429*f6aab3d8Srobert "(die = {0:x16}, decl_ctx = {1:p} (die "
430*f6aab3d8Srobert "{2:x16})) {3} name = '{4}')",
431061da546Spatrick die.GetOffset(), static_cast<void *>(context), context_die.GetOffset(),
432061da546Spatrick die.GetTagAsCString(), die.GetName());
433061da546Spatrick }
434061da546Spatrick
435061da546Spatrick Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
436061da546Spatrick if (type_ptr == DIE_IS_BEING_PARSED)
437061da546Spatrick return nullptr;
438061da546Spatrick if (type_ptr)
439061da546Spatrick return type_ptr->shared_from_this();
440061da546Spatrick // Set a bit that lets us know that we are currently parsing this
441061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
442061da546Spatrick
443061da546Spatrick ParsedDWARFTypeAttributes attrs(die);
444061da546Spatrick
445061da546Spatrick if (DWARFDIE signature_die = attrs.signature.Reference()) {
446061da546Spatrick if (TypeSP type_sp =
447061da546Spatrick ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) {
448061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
449061da546Spatrick if (clang::DeclContext *decl_ctx =
450061da546Spatrick GetCachedClangDeclContextForDIE(signature_die))
451061da546Spatrick LinkDeclContextToDIE(decl_ctx, die);
452061da546Spatrick return type_sp;
453061da546Spatrick }
454061da546Spatrick return nullptr;
455061da546Spatrick }
456061da546Spatrick
457061da546Spatrick if (type_is_new_ptr)
458061da546Spatrick *type_is_new_ptr = true;
459061da546Spatrick
460061da546Spatrick const dw_tag_t tag = die.Tag();
461061da546Spatrick
462061da546Spatrick TypeSP type_sp;
463061da546Spatrick
464061da546Spatrick switch (tag) {
465061da546Spatrick case DW_TAG_typedef:
466061da546Spatrick case DW_TAG_base_type:
467061da546Spatrick case DW_TAG_pointer_type:
468061da546Spatrick case DW_TAG_reference_type:
469061da546Spatrick case DW_TAG_rvalue_reference_type:
470061da546Spatrick case DW_TAG_const_type:
471061da546Spatrick case DW_TAG_restrict_type:
472061da546Spatrick case DW_TAG_volatile_type:
473061da546Spatrick case DW_TAG_atomic_type:
474061da546Spatrick case DW_TAG_unspecified_type: {
475061da546Spatrick type_sp = ParseTypeModifier(sc, die, attrs);
476061da546Spatrick break;
477061da546Spatrick }
478061da546Spatrick
479061da546Spatrick case DW_TAG_structure_type:
480061da546Spatrick case DW_TAG_union_type:
481061da546Spatrick case DW_TAG_class_type: {
482061da546Spatrick type_sp = ParseStructureLikeDIE(sc, die, attrs);
483061da546Spatrick break;
484061da546Spatrick }
485061da546Spatrick
486061da546Spatrick case DW_TAG_enumeration_type: {
487061da546Spatrick type_sp = ParseEnum(sc, die, attrs);
488061da546Spatrick break;
489061da546Spatrick }
490061da546Spatrick
491061da546Spatrick case DW_TAG_inlined_subroutine:
492061da546Spatrick case DW_TAG_subprogram:
493061da546Spatrick case DW_TAG_subroutine_type: {
494061da546Spatrick type_sp = ParseSubroutine(die, attrs);
495061da546Spatrick break;
496061da546Spatrick }
497061da546Spatrick case DW_TAG_array_type: {
498061da546Spatrick type_sp = ParseArrayType(die, attrs);
499061da546Spatrick break;
500061da546Spatrick }
501061da546Spatrick case DW_TAG_ptr_to_member_type: {
502061da546Spatrick type_sp = ParsePointerToMemberType(die, attrs);
503061da546Spatrick break;
504061da546Spatrick }
505061da546Spatrick default:
506061da546Spatrick dwarf->GetObjectFile()->GetModule()->ReportError(
507*f6aab3d8Srobert "[{0:x16}]: unhandled type tag {1:x4} ({2}), "
508*f6aab3d8Srobert "please file a bug and "
509061da546Spatrick "attach the file at the start of this error message",
510061da546Spatrick die.GetOffset(), tag, DW_TAG_value_to_name(tag));
511061da546Spatrick break;
512061da546Spatrick }
513061da546Spatrick
514061da546Spatrick // TODO: We should consider making the switch above exhaustive to simplify
515061da546Spatrick // control flow in ParseTypeFromDWARF. Then, we could simply replace this
516061da546Spatrick // return statement with a call to llvm_unreachable.
517061da546Spatrick return UpdateSymbolContextScopeForType(sc, die, type_sp);
518061da546Spatrick }
519061da546Spatrick
520061da546Spatrick lldb::TypeSP
ParseTypeModifier(const SymbolContext & sc,const DWARFDIE & die,ParsedDWARFTypeAttributes & attrs)521061da546Spatrick DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
522061da546Spatrick const DWARFDIE &die,
523061da546Spatrick ParsedDWARFTypeAttributes &attrs) {
524*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
525061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
526061da546Spatrick const dw_tag_t tag = die.Tag();
527dda28197Spatrick LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());
528061da546Spatrick Type::ResolveState resolve_state = Type::ResolveState::Unresolved;
529061da546Spatrick Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
530061da546Spatrick TypeSP type_sp;
531061da546Spatrick CompilerType clang_type;
532061da546Spatrick
533be691f3bSpatrick if (tag == DW_TAG_typedef) {
534be691f3bSpatrick // DeclContext will be populated when the clang type is materialized in
535be691f3bSpatrick // Type::ResolveCompilerType.
536be691f3bSpatrick PrepareContextToReceiveMembers(
537be691f3bSpatrick m_ast, GetClangASTImporter(),
538be691f3bSpatrick GetClangDeclContextContainingDIE(die, nullptr), die,
539be691f3bSpatrick attrs.name.GetCString());
540be691f3bSpatrick
541be691f3bSpatrick if (attrs.type.IsValid()) {
542061da546Spatrick // Try to parse a typedef from the (DWARF embedded in the) Clang
543061da546Spatrick // module file first as modules can contain typedef'ed
544061da546Spatrick // structures that have no names like:
545061da546Spatrick //
546061da546Spatrick // typedef struct { int a; } Foo;
547061da546Spatrick //
548061da546Spatrick // In this case we will have a structure with no name and a
549061da546Spatrick // typedef named "Foo" that points to this unnamed
550061da546Spatrick // structure. The name in the typedef is the only identifier for
551061da546Spatrick // the struct, so always try to get typedefs from Clang modules
552061da546Spatrick // if possible.
553061da546Spatrick //
554061da546Spatrick // The type_sp returned will be empty if the typedef doesn't
555061da546Spatrick // exist in a module file, so it is cheap to call this function
556061da546Spatrick // just to check.
557061da546Spatrick //
558061da546Spatrick // If we don't do this we end up creating a TypeSP that says
559061da546Spatrick // this is a typedef to type 0x123 (the DW_AT_type value would
560061da546Spatrick // be 0x123 in the DW_TAG_typedef), and this is the unnamed
561061da546Spatrick // structure type. We will have a hard time tracking down an
562061da546Spatrick // unnammed structure type in the module debug info, so we make
563061da546Spatrick // sure we don't get into this situation by always resolving
564061da546Spatrick // typedefs from the module.
565061da546Spatrick const DWARFDIE encoding_die = attrs.type.Reference();
566061da546Spatrick
567061da546Spatrick // First make sure that the die that this is typedef'ed to _is_
568061da546Spatrick // just a declaration (DW_AT_declaration == 1), not a full
569061da546Spatrick // definition since template types can't be represented in
570061da546Spatrick // modules since only concrete instances of templates are ever
571061da546Spatrick // emitted and modules won't contain those
572061da546Spatrick if (encoding_die &&
573061da546Spatrick encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
574061da546Spatrick type_sp = ParseTypeFromClangModule(sc, die, log);
575061da546Spatrick if (type_sp)
576061da546Spatrick return type_sp;
577061da546Spatrick }
578061da546Spatrick }
579be691f3bSpatrick }
580061da546Spatrick
581061da546Spatrick DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(),
582061da546Spatrick DW_TAG_value_to_name(tag), type_name_cstr,
583061da546Spatrick encoding_uid.Reference());
584061da546Spatrick
585061da546Spatrick switch (tag) {
586061da546Spatrick default:
587061da546Spatrick break;
588061da546Spatrick
589061da546Spatrick case DW_TAG_unspecified_type:
590061da546Spatrick if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") {
591061da546Spatrick resolve_state = Type::ResolveState::Full;
592061da546Spatrick clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);
593061da546Spatrick break;
594061da546Spatrick }
595061da546Spatrick // Fall through to base type below in case we can handle the type
596061da546Spatrick // there...
597*f6aab3d8Srobert [[fallthrough]];
598061da546Spatrick
599061da546Spatrick case DW_TAG_base_type:
600061da546Spatrick resolve_state = Type::ResolveState::Full;
601061da546Spatrick clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
602061da546Spatrick attrs.name.GetStringRef(), attrs.encoding,
603*f6aab3d8Srobert attrs.byte_size.value_or(0) * 8);
604061da546Spatrick break;
605061da546Spatrick
606061da546Spatrick case DW_TAG_pointer_type:
607061da546Spatrick encoding_data_type = Type::eEncodingIsPointerUID;
608061da546Spatrick break;
609061da546Spatrick case DW_TAG_reference_type:
610061da546Spatrick encoding_data_type = Type::eEncodingIsLValueReferenceUID;
611061da546Spatrick break;
612061da546Spatrick case DW_TAG_rvalue_reference_type:
613061da546Spatrick encoding_data_type = Type::eEncodingIsRValueReferenceUID;
614061da546Spatrick break;
615061da546Spatrick case DW_TAG_typedef:
616061da546Spatrick encoding_data_type = Type::eEncodingIsTypedefUID;
617061da546Spatrick break;
618061da546Spatrick case DW_TAG_const_type:
619061da546Spatrick encoding_data_type = Type::eEncodingIsConstUID;
620061da546Spatrick break;
621061da546Spatrick case DW_TAG_restrict_type:
622061da546Spatrick encoding_data_type = Type::eEncodingIsRestrictUID;
623061da546Spatrick break;
624061da546Spatrick case DW_TAG_volatile_type:
625061da546Spatrick encoding_data_type = Type::eEncodingIsVolatileUID;
626061da546Spatrick break;
627061da546Spatrick case DW_TAG_atomic_type:
628061da546Spatrick encoding_data_type = Type::eEncodingIsAtomicUID;
629061da546Spatrick break;
630061da546Spatrick }
631061da546Spatrick
632061da546Spatrick if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID ||
633061da546Spatrick encoding_data_type == Type::eEncodingIsTypedefUID)) {
634061da546Spatrick if (tag == DW_TAG_pointer_type) {
635061da546Spatrick DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);
636061da546Spatrick
637061da546Spatrick if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) {
638061da546Spatrick // Blocks have a __FuncPtr inside them which is a pointer to a
639061da546Spatrick // function of the proper type.
640061da546Spatrick
641be691f3bSpatrick for (DWARFDIE child_die : target_die.children()) {
642061da546Spatrick if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
643061da546Spatrick "__FuncPtr")) {
644061da546Spatrick DWARFDIE function_pointer_type =
645061da546Spatrick child_die.GetReferencedDIE(DW_AT_type);
646061da546Spatrick
647061da546Spatrick if (function_pointer_type) {
648061da546Spatrick DWARFDIE function_type =
649061da546Spatrick function_pointer_type.GetReferencedDIE(DW_AT_type);
650061da546Spatrick
651061da546Spatrick bool function_type_is_new_pointer;
652061da546Spatrick TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
653061da546Spatrick sc, function_type, &function_type_is_new_pointer);
654061da546Spatrick
655061da546Spatrick if (lldb_function_type_sp) {
656061da546Spatrick clang_type = m_ast.CreateBlockPointerType(
657061da546Spatrick lldb_function_type_sp->GetForwardCompilerType());
658061da546Spatrick encoding_data_type = Type::eEncodingIsUID;
659061da546Spatrick attrs.type.Clear();
660061da546Spatrick resolve_state = Type::ResolveState::Full;
661061da546Spatrick }
662061da546Spatrick }
663061da546Spatrick
664061da546Spatrick break;
665061da546Spatrick }
666061da546Spatrick }
667061da546Spatrick }
668061da546Spatrick }
669061da546Spatrick
670061da546Spatrick if (cu_language == eLanguageTypeObjC ||
671061da546Spatrick cu_language == eLanguageTypeObjC_plus_plus) {
672061da546Spatrick if (attrs.name) {
673061da546Spatrick if (attrs.name == "id") {
674061da546Spatrick if (log)
675061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
676061da546Spatrick log,
677*f6aab3d8Srobert "SymbolFileDWARF::ParseType (die = {0:x16}) {1} '{2}' "
678061da546Spatrick "is Objective-C 'id' built-in type.",
679061da546Spatrick die.GetOffset(), die.GetTagAsCString(), die.GetName());
680061da546Spatrick clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
681061da546Spatrick encoding_data_type = Type::eEncodingIsUID;
682061da546Spatrick attrs.type.Clear();
683061da546Spatrick resolve_state = Type::ResolveState::Full;
684061da546Spatrick } else if (attrs.name == "Class") {
685061da546Spatrick if (log)
686061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
687061da546Spatrick log,
688*f6aab3d8Srobert "SymbolFileDWARF::ParseType (die = {0:x16}) {1} '{2}' "
689061da546Spatrick "is Objective-C 'Class' built-in type.",
690061da546Spatrick die.GetOffset(), die.GetTagAsCString(), die.GetName());
691061da546Spatrick clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
692061da546Spatrick encoding_data_type = Type::eEncodingIsUID;
693061da546Spatrick attrs.type.Clear();
694061da546Spatrick resolve_state = Type::ResolveState::Full;
695061da546Spatrick } else if (attrs.name == "SEL") {
696061da546Spatrick if (log)
697061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
698061da546Spatrick log,
699*f6aab3d8Srobert "SymbolFileDWARF::ParseType (die = {0:x16}) {1} '{2}' "
700061da546Spatrick "is Objective-C 'selector' built-in type.",
701061da546Spatrick die.GetOffset(), die.GetTagAsCString(), die.GetName());
702061da546Spatrick clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
703061da546Spatrick encoding_data_type = Type::eEncodingIsUID;
704061da546Spatrick attrs.type.Clear();
705061da546Spatrick resolve_state = Type::ResolveState::Full;
706061da546Spatrick }
707061da546Spatrick } else if (encoding_data_type == Type::eEncodingIsPointerUID &&
708061da546Spatrick attrs.type.IsValid()) {
709061da546Spatrick // Clang sometimes erroneously emits id as objc_object*. In that
710061da546Spatrick // case we fix up the type to "id".
711061da546Spatrick
712061da546Spatrick const DWARFDIE encoding_die = attrs.type.Reference();
713061da546Spatrick
714061da546Spatrick if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {
715061da546Spatrick llvm::StringRef struct_name = encoding_die.GetName();
716061da546Spatrick if (struct_name == "objc_object") {
717061da546Spatrick if (log)
718061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
719061da546Spatrick log,
720*f6aab3d8Srobert "SymbolFileDWARF::ParseType (die = {0:x16}) {1} "
721*f6aab3d8Srobert "'{2}' is 'objc_object*', which we overrode to "
722061da546Spatrick "'id'.",
723061da546Spatrick die.GetOffset(), die.GetTagAsCString(), die.GetName());
724061da546Spatrick clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
725061da546Spatrick encoding_data_type = Type::eEncodingIsUID;
726061da546Spatrick attrs.type.Clear();
727061da546Spatrick resolve_state = Type::ResolveState::Full;
728061da546Spatrick }
729061da546Spatrick }
730061da546Spatrick }
731061da546Spatrick }
732061da546Spatrick }
733061da546Spatrick
734*f6aab3d8Srobert type_sp = dwarf->MakeType(
735*f6aab3d8Srobert die.GetID(), attrs.name, attrs.byte_size, nullptr,
736061da546Spatrick dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl,
737dda28197Spatrick clang_type, resolve_state, TypePayloadClang(GetOwningClangModule(die)));
738061da546Spatrick
739061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
740061da546Spatrick return type_sp;
741061da546Spatrick }
742061da546Spatrick
743*f6aab3d8Srobert ConstString
GetDIEClassTemplateParams(const DWARFDIE & die)744*f6aab3d8Srobert DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {
745*f6aab3d8Srobert if (llvm::StringRef(die.GetName()).contains("<"))
746*f6aab3d8Srobert return ConstString();
747*f6aab3d8Srobert
748*f6aab3d8Srobert TypeSystemClang::TemplateParameterInfos template_param_infos;
749*f6aab3d8Srobert if (ParseTemplateParameterInfos(die, template_param_infos)) {
750*f6aab3d8Srobert return ConstString(m_ast.PrintTemplateParams(template_param_infos));
751*f6aab3d8Srobert }
752*f6aab3d8Srobert return ConstString();
753*f6aab3d8Srobert }
754*f6aab3d8Srobert
ParseEnum(const SymbolContext & sc,const DWARFDIE & die,ParsedDWARFTypeAttributes & attrs)755061da546Spatrick TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
756061da546Spatrick const DWARFDIE &die,
757061da546Spatrick ParsedDWARFTypeAttributes &attrs) {
758*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
759061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
760061da546Spatrick const dw_tag_t tag = die.Tag();
761061da546Spatrick TypeSP type_sp;
762061da546Spatrick
763061da546Spatrick if (attrs.is_forward_declaration) {
764061da546Spatrick type_sp = ParseTypeFromClangModule(sc, die, log);
765061da546Spatrick if (type_sp)
766061da546Spatrick return type_sp;
767061da546Spatrick
768*f6aab3d8Srobert type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
769061da546Spatrick
770061da546Spatrick if (!type_sp) {
771061da546Spatrick SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
772061da546Spatrick if (debug_map_symfile) {
773061da546Spatrick // We weren't able to find a full declaration in this DWARF,
774061da546Spatrick // see if we have a declaration anywhere else...
775*f6aab3d8Srobert type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
776061da546Spatrick }
777061da546Spatrick }
778061da546Spatrick
779061da546Spatrick if (type_sp) {
780061da546Spatrick if (log) {
781061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
782061da546Spatrick log,
783*f6aab3d8Srobert "SymbolFileDWARF({0:p}) - {1:x16}}: {2} type \"{3}\" is a "
784*f6aab3d8Srobert "forward declaration, complete type is {4:x8}",
785061da546Spatrick static_cast<void *>(this), die.GetOffset(),
786061da546Spatrick DW_TAG_value_to_name(tag), attrs.name.GetCString(),
787061da546Spatrick type_sp->GetID());
788061da546Spatrick }
789061da546Spatrick
790061da546Spatrick // We found a real definition for this type elsewhere so lets use
791061da546Spatrick // it and cache the fact that we found a complete type for this
792061da546Spatrick // die
793061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
794061da546Spatrick clang::DeclContext *defn_decl_ctx =
795061da546Spatrick GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
796061da546Spatrick if (defn_decl_ctx)
797061da546Spatrick LinkDeclContextToDIE(defn_decl_ctx, die);
798061da546Spatrick return type_sp;
799061da546Spatrick }
800061da546Spatrick }
801061da546Spatrick DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
802061da546Spatrick DW_TAG_value_to_name(tag), type_name_cstr);
803061da546Spatrick
804061da546Spatrick CompilerType enumerator_clang_type;
805061da546Spatrick CompilerType clang_type;
806*f6aab3d8Srobert clang_type =
807*f6aab3d8Srobert CompilerType(m_ast.weak_from_this(),
808*f6aab3d8Srobert dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
809061da546Spatrick if (!clang_type) {
810061da546Spatrick if (attrs.type.IsValid()) {
811061da546Spatrick Type *enumerator_type =
812061da546Spatrick dwarf->ResolveTypeUID(attrs.type.Reference(), true);
813061da546Spatrick if (enumerator_type)
814061da546Spatrick enumerator_clang_type = enumerator_type->GetFullCompilerType();
815061da546Spatrick }
816061da546Spatrick
817061da546Spatrick if (!enumerator_clang_type) {
818061da546Spatrick if (attrs.byte_size) {
819061da546Spatrick enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
820061da546Spatrick "", DW_ATE_signed, *attrs.byte_size * 8);
821061da546Spatrick } else {
822061da546Spatrick enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt);
823061da546Spatrick }
824061da546Spatrick }
825061da546Spatrick
826061da546Spatrick clang_type = m_ast.CreateEnumerationType(
827*f6aab3d8Srobert attrs.name.GetStringRef(),
828*f6aab3d8Srobert GetClangDeclContextContainingDIE(die, nullptr),
829dda28197Spatrick GetOwningClangModule(die), attrs.decl, enumerator_clang_type,
830dda28197Spatrick attrs.is_scoped_enum);
831061da546Spatrick } else {
832dda28197Spatrick enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type);
833061da546Spatrick }
834061da546Spatrick
835dda28197Spatrick LinkDeclContextToDIE(TypeSystemClang::GetDeclContextForType(clang_type), die);
836061da546Spatrick
837*f6aab3d8Srobert type_sp = dwarf->MakeType(die.GetID(), attrs.name, attrs.byte_size, nullptr,
838*f6aab3d8Srobert dwarf->GetUID(attrs.type.Reference()),
839*f6aab3d8Srobert Type::eEncodingIsUID, &attrs.decl, clang_type,
840*f6aab3d8Srobert Type::ResolveState::Forward,
841dda28197Spatrick TypePayloadClang(GetOwningClangModule(die)));
842061da546Spatrick
843dda28197Spatrick if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) {
844061da546Spatrick if (die.HasChildren()) {
845061da546Spatrick bool is_signed = false;
846061da546Spatrick enumerator_clang_type.IsIntegerType(is_signed);
847061da546Spatrick ParseChildEnumerators(clang_type, is_signed,
848*f6aab3d8Srobert type_sp->GetByteSize(nullptr).value_or(0), die);
849061da546Spatrick }
850dda28197Spatrick TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);
851061da546Spatrick } else {
852061da546Spatrick dwarf->GetObjectFile()->GetModule()->ReportError(
853*f6aab3d8Srobert "DWARF DIE at {0:x16} named \"{1}\" was not able to start its "
854061da546Spatrick "definition.\nPlease file a bug and attach the file at the "
855061da546Spatrick "start of this error message",
856061da546Spatrick die.GetOffset(), attrs.name.GetCString());
857061da546Spatrick }
858061da546Spatrick return type_sp;
859061da546Spatrick }
860061da546Spatrick
861*f6aab3d8Srobert static clang::CallingConv
ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes & attrs)862*f6aab3d8Srobert ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes &attrs) {
863*f6aab3d8Srobert switch (attrs.calling_convention) {
864*f6aab3d8Srobert case llvm::dwarf::DW_CC_normal:
865*f6aab3d8Srobert return clang::CC_C;
866*f6aab3d8Srobert case llvm::dwarf::DW_CC_BORLAND_stdcall:
867*f6aab3d8Srobert return clang::CC_X86StdCall;
868*f6aab3d8Srobert case llvm::dwarf::DW_CC_BORLAND_msfastcall:
869*f6aab3d8Srobert return clang::CC_X86FastCall;
870*f6aab3d8Srobert case llvm::dwarf::DW_CC_LLVM_vectorcall:
871*f6aab3d8Srobert return clang::CC_X86VectorCall;
872*f6aab3d8Srobert case llvm::dwarf::DW_CC_BORLAND_pascal:
873*f6aab3d8Srobert return clang::CC_X86Pascal;
874*f6aab3d8Srobert case llvm::dwarf::DW_CC_LLVM_Win64:
875*f6aab3d8Srobert return clang::CC_Win64;
876*f6aab3d8Srobert case llvm::dwarf::DW_CC_LLVM_X86_64SysV:
877*f6aab3d8Srobert return clang::CC_X86_64SysV;
878*f6aab3d8Srobert case llvm::dwarf::DW_CC_LLVM_X86RegCall:
879*f6aab3d8Srobert return clang::CC_X86RegCall;
880*f6aab3d8Srobert default:
881*f6aab3d8Srobert break;
882*f6aab3d8Srobert }
883*f6aab3d8Srobert
884*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
885*f6aab3d8Srobert LLDB_LOG(log, "Unsupported DW_AT_calling_convention value: {0}",
886*f6aab3d8Srobert attrs.calling_convention);
887*f6aab3d8Srobert // Use the default calling convention as a fallback.
888*f6aab3d8Srobert return clang::CC_C;
889*f6aab3d8Srobert }
890*f6aab3d8Srobert
ParseSubroutine(const DWARFDIE & die,ParsedDWARFTypeAttributes & attrs)891061da546Spatrick TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
892061da546Spatrick ParsedDWARFTypeAttributes &attrs) {
893*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
894061da546Spatrick
895061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
896061da546Spatrick const dw_tag_t tag = die.Tag();
897061da546Spatrick
898061da546Spatrick bool is_variadic = false;
899061da546Spatrick bool is_static = false;
900061da546Spatrick bool has_template_params = false;
901061da546Spatrick
902061da546Spatrick unsigned type_quals = 0;
903061da546Spatrick
904061da546Spatrick std::string object_pointer_name;
905061da546Spatrick if (attrs.object_pointer) {
906061da546Spatrick const char *object_pointer_name_cstr = attrs.object_pointer.GetName();
907061da546Spatrick if (object_pointer_name_cstr)
908061da546Spatrick object_pointer_name = object_pointer_name_cstr;
909061da546Spatrick }
910061da546Spatrick
911061da546Spatrick DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
912061da546Spatrick DW_TAG_value_to_name(tag), type_name_cstr);
913061da546Spatrick
914061da546Spatrick CompilerType return_clang_type;
915*f6aab3d8Srobert Type *func_type = nullptr;
916061da546Spatrick
917061da546Spatrick if (attrs.type.IsValid())
918061da546Spatrick func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
919061da546Spatrick
920061da546Spatrick if (func_type)
921061da546Spatrick return_clang_type = func_type->GetForwardCompilerType();
922061da546Spatrick else
923061da546Spatrick return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);
924061da546Spatrick
925061da546Spatrick std::vector<CompilerType> function_param_types;
926061da546Spatrick std::vector<clang::ParmVarDecl *> function_param_decls;
927061da546Spatrick
928061da546Spatrick // Parse the function children for the parameters
929061da546Spatrick
930061da546Spatrick DWARFDIE decl_ctx_die;
931061da546Spatrick clang::DeclContext *containing_decl_ctx =
932061da546Spatrick GetClangDeclContextContainingDIE(die, &decl_ctx_die);
933061da546Spatrick const clang::Decl::Kind containing_decl_kind =
934061da546Spatrick containing_decl_ctx->getDeclKind();
935061da546Spatrick
936061da546Spatrick bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
937061da546Spatrick // Start off static. This will be set to false in
938061da546Spatrick // ParseChildParameters(...) if we find a "this" parameters as the
939061da546Spatrick // first parameter
940061da546Spatrick if (is_cxx_method) {
941061da546Spatrick is_static = true;
942061da546Spatrick }
943061da546Spatrick
944061da546Spatrick if (die.HasChildren()) {
945061da546Spatrick bool skip_artificial = true;
946061da546Spatrick ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static,
947061da546Spatrick is_variadic, has_template_params,
948061da546Spatrick function_param_types, function_param_decls,
949061da546Spatrick type_quals);
950061da546Spatrick }
951061da546Spatrick
952061da546Spatrick bool ignore_containing_context = false;
953061da546Spatrick // Check for templatized class member functions. If we had any
954061da546Spatrick // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
955061da546Spatrick // the DW_TAG_subprogram DIE, then we can't let this become a method in
956061da546Spatrick // a class. Why? Because templatized functions are only emitted if one
957061da546Spatrick // of the templatized methods is used in the current compile unit and
958061da546Spatrick // we will end up with classes that may or may not include these member
959061da546Spatrick // functions and this means one class won't match another class
960061da546Spatrick // definition and it affects our ability to use a class in the clang
961061da546Spatrick // expression parser. So for the greater good, we currently must not
962061da546Spatrick // allow any template member functions in a class definition.
963061da546Spatrick if (is_cxx_method && has_template_params) {
964061da546Spatrick ignore_containing_context = true;
965061da546Spatrick is_cxx_method = false;
966061da546Spatrick }
967061da546Spatrick
968*f6aab3d8Srobert clang::CallingConv calling_convention =
969*f6aab3d8Srobert ConvertDWARFCallingConventionToClang(attrs);
970*f6aab3d8Srobert
971061da546Spatrick // clang_type will get the function prototype clang type after this
972061da546Spatrick // call
973*f6aab3d8Srobert CompilerType clang_type =
974*f6aab3d8Srobert m_ast.CreateFunctionType(return_clang_type, function_param_types.data(),
975*f6aab3d8Srobert function_param_types.size(), is_variadic,
976*f6aab3d8Srobert type_quals, calling_convention, attrs.ref_qual);
977061da546Spatrick
978061da546Spatrick if (attrs.name) {
979061da546Spatrick bool type_handled = false;
980061da546Spatrick if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
981061da546Spatrick ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true);
982061da546Spatrick if (objc_method.IsValid(true)) {
983061da546Spatrick CompilerType class_opaque_type;
984061da546Spatrick ConstString class_name(objc_method.GetClassName());
985061da546Spatrick if (class_name) {
986061da546Spatrick TypeSP complete_objc_class_type_sp(
987061da546Spatrick dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(),
988061da546Spatrick class_name, false));
989061da546Spatrick
990061da546Spatrick if (complete_objc_class_type_sp) {
991061da546Spatrick CompilerType type_clang_forward_type =
992061da546Spatrick complete_objc_class_type_sp->GetForwardCompilerType();
993dda28197Spatrick if (TypeSystemClang::IsObjCObjectOrInterfaceType(
994061da546Spatrick type_clang_forward_type))
995061da546Spatrick class_opaque_type = type_clang_forward_type;
996061da546Spatrick }
997061da546Spatrick }
998061da546Spatrick
999061da546Spatrick if (class_opaque_type) {
1000061da546Spatrick // If accessibility isn't set to anything valid, assume public
1001061da546Spatrick // for now...
1002061da546Spatrick if (attrs.accessibility == eAccessNone)
1003061da546Spatrick attrs.accessibility = eAccessPublic;
1004061da546Spatrick
1005061da546Spatrick clang::ObjCMethodDecl *objc_method_decl =
1006061da546Spatrick m_ast.AddMethodToObjCObjectType(
1007061da546Spatrick class_opaque_type, attrs.name.GetCString(), clang_type,
1008061da546Spatrick attrs.accessibility, attrs.is_artificial, is_variadic,
1009061da546Spatrick attrs.is_objc_direct_call);
1010*f6aab3d8Srobert type_handled = objc_method_decl != nullptr;
1011061da546Spatrick if (type_handled) {
1012061da546Spatrick LinkDeclContextToDIE(objc_method_decl, die);
1013061da546Spatrick m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID());
1014061da546Spatrick } else {
1015061da546Spatrick dwarf->GetObjectFile()->GetModule()->ReportError(
1016*f6aab3d8Srobert "[{0:x16}]: invalid Objective-C method {1:x4} ({2}), "
1017061da546Spatrick "please file a bug and attach the file at the start of "
1018061da546Spatrick "this error message",
1019061da546Spatrick die.GetOffset(), tag, DW_TAG_value_to_name(tag));
1020061da546Spatrick }
1021061da546Spatrick }
1022061da546Spatrick } else if (is_cxx_method) {
1023061da546Spatrick // Look at the parent of this DIE and see if is is a class or
1024061da546Spatrick // struct and see if this is actually a C++ method
1025061da546Spatrick Type *class_type = dwarf->ResolveType(decl_ctx_die);
1026061da546Spatrick if (class_type) {
1027061da546Spatrick if (class_type->GetID() != decl_ctx_die.GetID() ||
1028061da546Spatrick IsClangModuleFwdDecl(decl_ctx_die)) {
1029061da546Spatrick
1030061da546Spatrick // We uniqued the parent class of this function to another
1031061da546Spatrick // class so we now need to associate all dies under
1032061da546Spatrick // "decl_ctx_die" to DIEs in the DIE for "class_type"...
1033061da546Spatrick DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
1034061da546Spatrick
1035061da546Spatrick if (class_type_die) {
1036061da546Spatrick std::vector<DWARFDIE> failures;
1037061da546Spatrick
1038061da546Spatrick CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
1039061da546Spatrick class_type, failures);
1040061da546Spatrick
1041061da546Spatrick // FIXME do something with these failures that's
1042061da546Spatrick // smarter than just dropping them on the ground.
1043061da546Spatrick // Unfortunately classes don't like having stuff added
1044061da546Spatrick // to them after their definitions are complete...
1045061da546Spatrick
1046061da546Spatrick Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
1047061da546Spatrick if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
1048061da546Spatrick return type_ptr->shared_from_this();
1049061da546Spatrick }
1050061da546Spatrick }
1051061da546Spatrick }
1052061da546Spatrick
1053061da546Spatrick if (attrs.specification.IsValid()) {
1054061da546Spatrick // We have a specification which we are going to base our
1055061da546Spatrick // function prototype off of, so we need this type to be
1056061da546Spatrick // completed so that the m_die_to_decl_ctx for the method in
1057061da546Spatrick // the specification has a valid clang decl context.
1058061da546Spatrick class_type->GetForwardCompilerType();
1059061da546Spatrick // If we have a specification, then the function type should
1060061da546Spatrick // have been made with the specification and not with this
1061061da546Spatrick // die.
1062061da546Spatrick DWARFDIE spec_die = attrs.specification.Reference();
1063061da546Spatrick clang::DeclContext *spec_clang_decl_ctx =
1064061da546Spatrick GetClangDeclContextForDIE(spec_die);
1065061da546Spatrick if (spec_clang_decl_ctx) {
1066061da546Spatrick LinkDeclContextToDIE(spec_clang_decl_ctx, die);
1067061da546Spatrick } else {
1068061da546Spatrick dwarf->GetObjectFile()->GetModule()->ReportWarning(
1069*f6aab3d8Srobert "{0:x8}: DW_AT_specification({1:x16}"
1070061da546Spatrick ") has no decl\n",
1071061da546Spatrick die.GetID(), spec_die.GetOffset());
1072061da546Spatrick }
1073061da546Spatrick type_handled = true;
1074061da546Spatrick } else if (attrs.abstract_origin.IsValid()) {
1075061da546Spatrick // We have a specification which we are going to base our
1076061da546Spatrick // function prototype off of, so we need this type to be
1077061da546Spatrick // completed so that the m_die_to_decl_ctx for the method in
1078061da546Spatrick // the abstract origin has a valid clang decl context.
1079061da546Spatrick class_type->GetForwardCompilerType();
1080061da546Spatrick
1081061da546Spatrick DWARFDIE abs_die = attrs.abstract_origin.Reference();
1082061da546Spatrick clang::DeclContext *abs_clang_decl_ctx =
1083061da546Spatrick GetClangDeclContextForDIE(abs_die);
1084061da546Spatrick if (abs_clang_decl_ctx) {
1085061da546Spatrick LinkDeclContextToDIE(abs_clang_decl_ctx, die);
1086061da546Spatrick } else {
1087061da546Spatrick dwarf->GetObjectFile()->GetModule()->ReportWarning(
1088*f6aab3d8Srobert "{0:x8}: DW_AT_abstract_origin({1:x16}"
1089061da546Spatrick ") has no decl\n",
1090061da546Spatrick die.GetID(), abs_die.GetOffset());
1091061da546Spatrick }
1092061da546Spatrick type_handled = true;
1093061da546Spatrick } else {
1094061da546Spatrick CompilerType class_opaque_type =
1095061da546Spatrick class_type->GetForwardCompilerType();
1096dda28197Spatrick if (TypeSystemClang::IsCXXClassType(class_opaque_type)) {
1097*f6aab3d8Srobert if (class_opaque_type.IsBeingDefined()) {
1098061da546Spatrick if (!is_static && !die.HasChildren()) {
1099061da546Spatrick // We have a C++ member function with no children (this
1100061da546Spatrick // pointer!) and clang will get mad if we try and make
1101061da546Spatrick // a function that isn't well formed in the DWARF, so
1102061da546Spatrick // we will just skip it...
1103061da546Spatrick type_handled = true;
1104061da546Spatrick } else {
1105061da546Spatrick llvm::PrettyStackTraceFormat stack_trace(
1106061da546Spatrick "SymbolFileDWARF::ParseType() is adding a method "
1107061da546Spatrick "%s to class %s in DIE 0x%8.8" PRIx64 " from %s",
1108061da546Spatrick attrs.name.GetCString(),
1109061da546Spatrick class_type->GetName().GetCString(), die.GetID(),
1110*f6aab3d8Srobert dwarf->GetObjectFile()->GetFileSpec().GetPath().c_str());
1111061da546Spatrick
1112061da546Spatrick const bool is_attr_used = false;
1113061da546Spatrick // Neither GCC 4.2 nor clang++ currently set a valid
1114061da546Spatrick // accessibility in the DWARF for C++ methods...
1115061da546Spatrick // Default to public for now...
1116061da546Spatrick if (attrs.accessibility == eAccessNone)
1117061da546Spatrick attrs.accessibility = eAccessPublic;
1118061da546Spatrick
1119061da546Spatrick clang::CXXMethodDecl *cxx_method_decl =
1120061da546Spatrick m_ast.AddMethodToCXXRecordType(
1121061da546Spatrick class_opaque_type.GetOpaqueQualType(),
1122061da546Spatrick attrs.name.GetCString(), attrs.mangled_name,
1123061da546Spatrick clang_type, attrs.accessibility, attrs.is_virtual,
1124061da546Spatrick is_static, attrs.is_inline, attrs.is_explicit,
1125061da546Spatrick is_attr_used, attrs.is_artificial);
1126061da546Spatrick
1127*f6aab3d8Srobert type_handled = cxx_method_decl != nullptr;
1128061da546Spatrick // Artificial methods are always handled even when we
1129061da546Spatrick // don't create a new declaration for them.
1130061da546Spatrick type_handled |= attrs.is_artificial;
1131061da546Spatrick
1132061da546Spatrick if (cxx_method_decl) {
1133061da546Spatrick LinkDeclContextToDIE(cxx_method_decl, die);
1134061da546Spatrick
1135061da546Spatrick ClangASTMetadata metadata;
1136061da546Spatrick metadata.SetUserID(die.GetID());
1137061da546Spatrick
1138061da546Spatrick if (!object_pointer_name.empty()) {
1139*f6aab3d8Srobert metadata.SetObjectPtrName(object_pointer_name.c_str());
1140061da546Spatrick LLDB_LOGF(log,
1141061da546Spatrick "Setting object pointer name: %s on method "
1142061da546Spatrick "object %p.\n",
1143061da546Spatrick object_pointer_name.c_str(),
1144061da546Spatrick static_cast<void *>(cxx_method_decl));
1145061da546Spatrick }
1146061da546Spatrick m_ast.SetMetadata(cxx_method_decl, metadata);
1147061da546Spatrick } else {
1148061da546Spatrick ignore_containing_context = true;
1149061da546Spatrick }
1150061da546Spatrick }
1151061da546Spatrick } else {
1152061da546Spatrick // We were asked to parse the type for a method in a
1153061da546Spatrick // class, yet the class hasn't been asked to complete
1154061da546Spatrick // itself through the clang::ExternalASTSource protocol,
1155061da546Spatrick // so we need to just have the class complete itself and
1156061da546Spatrick // do things the right way, then our
1157061da546Spatrick // DIE should then have an entry in the
1158061da546Spatrick // dwarf->GetDIEToType() map. First
1159061da546Spatrick // we need to modify the dwarf->GetDIEToType() so it
1160061da546Spatrick // doesn't think we are trying to parse this DIE
1161061da546Spatrick // anymore...
1162061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = NULL;
1163061da546Spatrick
1164061da546Spatrick // Now we get the full type to force our class type to
1165061da546Spatrick // complete itself using the clang::ExternalASTSource
1166061da546Spatrick // protocol which will parse all base classes and all
1167061da546Spatrick // methods (including the method for this DIE).
1168061da546Spatrick class_type->GetFullCompilerType();
1169061da546Spatrick
1170061da546Spatrick // The type for this DIE should have been filled in the
1171061da546Spatrick // function call above
1172061da546Spatrick Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
1173061da546Spatrick if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
1174061da546Spatrick return type_ptr->shared_from_this();
1175061da546Spatrick }
1176061da546Spatrick
1177061da546Spatrick // FIXME This is fixing some even uglier behavior but we
1178061da546Spatrick // really need to
1179061da546Spatrick // uniq the methods of each class as well as the class
1180061da546Spatrick // itself. <rdar://problem/11240464>
1181061da546Spatrick type_handled = true;
1182061da546Spatrick }
1183061da546Spatrick }
1184061da546Spatrick }
1185061da546Spatrick }
1186061da546Spatrick }
1187061da546Spatrick }
1188061da546Spatrick
1189061da546Spatrick if (!type_handled) {
1190061da546Spatrick clang::FunctionDecl *function_decl = nullptr;
1191061da546Spatrick clang::FunctionDecl *template_function_decl = nullptr;
1192061da546Spatrick
1193061da546Spatrick if (attrs.abstract_origin.IsValid()) {
1194061da546Spatrick DWARFDIE abs_die = attrs.abstract_origin.Reference();
1195061da546Spatrick
1196061da546Spatrick if (dwarf->ResolveType(abs_die)) {
1197061da546Spatrick function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(
1198061da546Spatrick GetCachedClangDeclContextForDIE(abs_die));
1199061da546Spatrick
1200061da546Spatrick if (function_decl) {
1201061da546Spatrick LinkDeclContextToDIE(function_decl, die);
1202061da546Spatrick }
1203061da546Spatrick }
1204061da546Spatrick }
1205061da546Spatrick
1206061da546Spatrick if (!function_decl) {
1207be691f3bSpatrick char *name_buf = nullptr;
1208be691f3bSpatrick llvm::StringRef name = attrs.name.GetStringRef();
1209dda28197Spatrick
1210dda28197Spatrick // We currently generate function templates with template parameters in
1211dda28197Spatrick // their name. In order to get closer to the AST that clang generates
1212dda28197Spatrick // we want to strip these from the name when creating the AST.
1213dda28197Spatrick if (attrs.mangled_name) {
1214dda28197Spatrick llvm::ItaniumPartialDemangler D;
1215be691f3bSpatrick if (!D.partialDemangle(attrs.mangled_name)) {
1216be691f3bSpatrick name_buf = D.getFunctionBaseName(nullptr, nullptr);
1217be691f3bSpatrick name = name_buf;
1218be691f3bSpatrick }
1219dda28197Spatrick }
1220dda28197Spatrick
1221061da546Spatrick // We just have a function that isn't part of a class
1222061da546Spatrick function_decl = m_ast.CreateFunctionDeclaration(
1223061da546Spatrick ignore_containing_context ? m_ast.GetTranslationUnitDecl()
1224061da546Spatrick : containing_decl_ctx,
1225dda28197Spatrick GetOwningClangModule(die), name, clang_type, attrs.storage,
1226061da546Spatrick attrs.is_inline);
1227be691f3bSpatrick std::free(name_buf);
1228061da546Spatrick
1229061da546Spatrick if (has_template_params) {
1230dda28197Spatrick TypeSystemClang::TemplateParameterInfos template_param_infos;
1231061da546Spatrick ParseTemplateParameterInfos(die, template_param_infos);
1232061da546Spatrick template_function_decl = m_ast.CreateFunctionDeclaration(
1233061da546Spatrick ignore_containing_context ? m_ast.GetTranslationUnitDecl()
1234061da546Spatrick : containing_decl_ctx,
1235be691f3bSpatrick GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type,
1236dda28197Spatrick attrs.storage, attrs.is_inline);
1237061da546Spatrick clang::FunctionTemplateDecl *func_template_decl =
1238061da546Spatrick m_ast.CreateFunctionTemplateDecl(
1239dda28197Spatrick containing_decl_ctx, GetOwningClangModule(die),
1240be691f3bSpatrick template_function_decl, template_param_infos);
1241061da546Spatrick m_ast.CreateFunctionTemplateSpecializationInfo(
1242dda28197Spatrick template_function_decl, func_template_decl, template_param_infos);
1243061da546Spatrick }
1244061da546Spatrick
1245061da546Spatrick lldbassert(function_decl);
1246061da546Spatrick
1247061da546Spatrick if (function_decl) {
1248*f6aab3d8Srobert // Attach an asm(<mangled_name>) label to the FunctionDecl.
1249*f6aab3d8Srobert // This ensures that clang::CodeGen emits function calls
1250*f6aab3d8Srobert // using symbols that are mangled according to the DW_AT_linkage_name.
1251*f6aab3d8Srobert // If we didn't do this, the external symbols wouldn't exactly
1252*f6aab3d8Srobert // match the mangled name LLDB knows about and the IRExecutionUnit
1253*f6aab3d8Srobert // would have to fall back to searching object files for
1254*f6aab3d8Srobert // approximately matching function names. The motivating
1255*f6aab3d8Srobert // example is generating calls to ABI-tagged template functions.
1256*f6aab3d8Srobert // This is done separately for member functions in
1257*f6aab3d8Srobert // AddMethodToCXXRecordType.
1258*f6aab3d8Srobert if (attrs.mangled_name)
1259*f6aab3d8Srobert function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
1260*f6aab3d8Srobert m_ast.getASTContext(), attrs.mangled_name, /*literal=*/false));
1261*f6aab3d8Srobert
1262061da546Spatrick LinkDeclContextToDIE(function_decl, die);
1263061da546Spatrick
1264061da546Spatrick if (!function_param_decls.empty()) {
1265be691f3bSpatrick m_ast.SetFunctionParameters(function_decl, function_param_decls);
1266061da546Spatrick if (template_function_decl)
1267061da546Spatrick m_ast.SetFunctionParameters(template_function_decl,
1268be691f3bSpatrick function_param_decls);
1269061da546Spatrick }
1270061da546Spatrick
1271061da546Spatrick ClangASTMetadata metadata;
1272061da546Spatrick metadata.SetUserID(die.GetID());
1273061da546Spatrick
1274061da546Spatrick if (!object_pointer_name.empty()) {
1275061da546Spatrick metadata.SetObjectPtrName(object_pointer_name.c_str());
1276061da546Spatrick LLDB_LOGF(log,
1277061da546Spatrick "Setting object pointer name: %s on function "
1278061da546Spatrick "object %p.",
1279061da546Spatrick object_pointer_name.c_str(),
1280061da546Spatrick static_cast<void *>(function_decl));
1281061da546Spatrick }
1282061da546Spatrick m_ast.SetMetadata(function_decl, metadata);
1283061da546Spatrick }
1284061da546Spatrick }
1285061da546Spatrick }
1286061da546Spatrick }
1287*f6aab3d8Srobert return dwarf->MakeType(
1288*f6aab3d8Srobert die.GetID(), attrs.name, std::nullopt, nullptr, LLDB_INVALID_UID,
1289061da546Spatrick Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Full);
1290061da546Spatrick }
1291061da546Spatrick
1292*f6aab3d8Srobert TypeSP
ParseArrayType(const DWARFDIE & die,const ParsedDWARFTypeAttributes & attrs)1293*f6aab3d8Srobert DWARFASTParserClang::ParseArrayType(const DWARFDIE &die,
1294*f6aab3d8Srobert const ParsedDWARFTypeAttributes &attrs) {
1295061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
1296061da546Spatrick
1297061da546Spatrick DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
1298061da546Spatrick DW_TAG_value_to_name(tag), type_name_cstr);
1299061da546Spatrick
1300061da546Spatrick DWARFDIE type_die = attrs.type.Reference();
1301061da546Spatrick Type *element_type = dwarf->ResolveTypeUID(type_die, true);
1302061da546Spatrick
1303061da546Spatrick if (!element_type)
1304061da546Spatrick return nullptr;
1305061da546Spatrick
1306*f6aab3d8Srobert std::optional<SymbolFile::ArrayInfo> array_info = ParseChildArrayInfo(die);
1307*f6aab3d8Srobert uint32_t byte_stride = attrs.byte_stride;
1308*f6aab3d8Srobert uint32_t bit_stride = attrs.bit_stride;
1309061da546Spatrick if (array_info) {
1310*f6aab3d8Srobert byte_stride = array_info->byte_stride;
1311*f6aab3d8Srobert bit_stride = array_info->bit_stride;
1312061da546Spatrick }
1313*f6aab3d8Srobert if (byte_stride == 0 && bit_stride == 0)
1314*f6aab3d8Srobert byte_stride = element_type->GetByteSize(nullptr).value_or(0);
1315061da546Spatrick CompilerType array_element_type = element_type->GetForwardCompilerType();
1316*f6aab3d8Srobert TypeSystemClang::RequireCompleteType(array_element_type);
1317061da546Spatrick
1318*f6aab3d8Srobert uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
1319061da546Spatrick CompilerType clang_type;
1320061da546Spatrick if (array_info && array_info->element_orders.size() > 0) {
1321061da546Spatrick uint64_t num_elements = 0;
1322061da546Spatrick auto end = array_info->element_orders.rend();
1323061da546Spatrick for (auto pos = array_info->element_orders.rbegin(); pos != end; ++pos) {
1324061da546Spatrick num_elements = *pos;
1325061da546Spatrick clang_type = m_ast.CreateArrayType(array_element_type, num_elements,
1326061da546Spatrick attrs.is_vector);
1327061da546Spatrick array_element_type = clang_type;
1328061da546Spatrick array_element_bit_stride = num_elements
1329061da546Spatrick ? array_element_bit_stride * num_elements
1330061da546Spatrick : array_element_bit_stride;
1331061da546Spatrick }
1332061da546Spatrick } else {
1333061da546Spatrick clang_type =
1334061da546Spatrick m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector);
1335061da546Spatrick }
1336061da546Spatrick ConstString empty_name;
1337*f6aab3d8Srobert TypeSP type_sp =
1338*f6aab3d8Srobert dwarf->MakeType(die.GetID(), empty_name, array_element_bit_stride / 8,
1339*f6aab3d8Srobert nullptr, dwarf->GetUID(type_die), Type::eEncodingIsUID,
1340*f6aab3d8Srobert &attrs.decl, clang_type, Type::ResolveState::Full);
1341061da546Spatrick type_sp->SetEncodingType(element_type);
1342061da546Spatrick const clang::Type *type = ClangUtil::GetQualType(clang_type).getTypePtr();
1343061da546Spatrick m_ast.SetMetadataAsUserID(type, die.GetID());
1344061da546Spatrick return type_sp;
1345061da546Spatrick }
1346061da546Spatrick
ParsePointerToMemberType(const DWARFDIE & die,const ParsedDWARFTypeAttributes & attrs)1347061da546Spatrick TypeSP DWARFASTParserClang::ParsePointerToMemberType(
1348061da546Spatrick const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs) {
1349061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
1350061da546Spatrick Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
1351061da546Spatrick Type *class_type =
1352061da546Spatrick dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
1353061da546Spatrick
1354061da546Spatrick CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
1355be691f3bSpatrick CompilerType class_clang_type = class_type->GetForwardCompilerType();
1356061da546Spatrick
1357dda28197Spatrick CompilerType clang_type = TypeSystemClang::CreateMemberPointerType(
1358061da546Spatrick class_clang_type, pointee_clang_type);
1359061da546Spatrick
1360*f6aab3d8Srobert if (std::optional<uint64_t> clang_type_size =
1361061da546Spatrick clang_type.GetByteSize(nullptr)) {
1362*f6aab3d8Srobert return dwarf->MakeType(die.GetID(), attrs.name, *clang_type_size, nullptr,
1363*f6aab3d8Srobert LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr,
1364*f6aab3d8Srobert clang_type, Type::ResolveState::Forward);
1365061da546Spatrick }
1366061da546Spatrick return nullptr;
1367061da546Spatrick }
1368061da546Spatrick
ParseInheritance(const DWARFDIE & die,const DWARFDIE & parent_die,const CompilerType class_clang_type,const AccessType default_accessibility,const lldb::ModuleSP & module_sp,std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> & base_classes,ClangASTImporter::LayoutInfo & layout_info)1369*f6aab3d8Srobert void DWARFASTParserClang::ParseInheritance(
1370*f6aab3d8Srobert const DWARFDIE &die, const DWARFDIE &parent_die,
1371*f6aab3d8Srobert const CompilerType class_clang_type, const AccessType default_accessibility,
1372*f6aab3d8Srobert const lldb::ModuleSP &module_sp,
1373*f6aab3d8Srobert std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
1374*f6aab3d8Srobert ClangASTImporter::LayoutInfo &layout_info) {
1375*f6aab3d8Srobert auto ast =
1376*f6aab3d8Srobert class_clang_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
1377*f6aab3d8Srobert if (ast == nullptr)
1378*f6aab3d8Srobert return;
1379*f6aab3d8Srobert
1380*f6aab3d8Srobert // TODO: implement DW_TAG_inheritance type parsing.
1381*f6aab3d8Srobert DWARFAttributes attributes;
1382*f6aab3d8Srobert const size_t num_attributes = die.GetAttributes(attributes);
1383*f6aab3d8Srobert if (num_attributes == 0)
1384*f6aab3d8Srobert return;
1385*f6aab3d8Srobert
1386*f6aab3d8Srobert DWARFFormValue encoding_form;
1387*f6aab3d8Srobert AccessType accessibility = default_accessibility;
1388*f6aab3d8Srobert bool is_virtual = false;
1389*f6aab3d8Srobert bool is_base_of_class = true;
1390*f6aab3d8Srobert off_t member_byte_offset = 0;
1391*f6aab3d8Srobert
1392*f6aab3d8Srobert for (uint32_t i = 0; i < num_attributes; ++i) {
1393*f6aab3d8Srobert const dw_attr_t attr = attributes.AttributeAtIndex(i);
1394*f6aab3d8Srobert DWARFFormValue form_value;
1395*f6aab3d8Srobert if (attributes.ExtractFormValueAtIndex(i, form_value)) {
1396*f6aab3d8Srobert switch (attr) {
1397*f6aab3d8Srobert case DW_AT_type:
1398*f6aab3d8Srobert encoding_form = form_value;
1399*f6aab3d8Srobert break;
1400*f6aab3d8Srobert case DW_AT_data_member_location:
1401*f6aab3d8Srobert if (form_value.BlockData()) {
1402*f6aab3d8Srobert Value initialValue(0);
1403*f6aab3d8Srobert Value memberOffset(0);
1404*f6aab3d8Srobert const DWARFDataExtractor &debug_info_data = die.GetData();
1405*f6aab3d8Srobert uint32_t block_length = form_value.Unsigned();
1406*f6aab3d8Srobert uint32_t block_offset =
1407*f6aab3d8Srobert form_value.BlockData() - debug_info_data.GetDataStart();
1408*f6aab3d8Srobert if (DWARFExpression::Evaluate(
1409*f6aab3d8Srobert nullptr, nullptr, module_sp,
1410*f6aab3d8Srobert DataExtractor(debug_info_data, block_offset, block_length),
1411*f6aab3d8Srobert die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
1412*f6aab3d8Srobert memberOffset, nullptr)) {
1413*f6aab3d8Srobert member_byte_offset = memberOffset.ResolveValue(nullptr).UInt();
1414*f6aab3d8Srobert }
1415*f6aab3d8Srobert } else {
1416*f6aab3d8Srobert // With DWARF 3 and later, if the value is an integer constant,
1417*f6aab3d8Srobert // this form value is the offset in bytes from the beginning of
1418*f6aab3d8Srobert // the containing entity.
1419*f6aab3d8Srobert member_byte_offset = form_value.Unsigned();
1420*f6aab3d8Srobert }
1421*f6aab3d8Srobert break;
1422*f6aab3d8Srobert
1423*f6aab3d8Srobert case DW_AT_accessibility:
1424*f6aab3d8Srobert accessibility = DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned());
1425*f6aab3d8Srobert break;
1426*f6aab3d8Srobert
1427*f6aab3d8Srobert case DW_AT_virtuality:
1428*f6aab3d8Srobert is_virtual = form_value.Boolean();
1429*f6aab3d8Srobert break;
1430*f6aab3d8Srobert
1431*f6aab3d8Srobert default:
1432*f6aab3d8Srobert break;
1433*f6aab3d8Srobert }
1434*f6aab3d8Srobert }
1435*f6aab3d8Srobert }
1436*f6aab3d8Srobert
1437*f6aab3d8Srobert Type *base_class_type = die.ResolveTypeUID(encoding_form.Reference());
1438*f6aab3d8Srobert if (base_class_type == nullptr) {
1439*f6aab3d8Srobert module_sp->ReportError("{0:x16}: DW_TAG_inheritance failed to "
1440*f6aab3d8Srobert "resolve the base class at {1:x16}"
1441*f6aab3d8Srobert " from enclosing type {2:x16}. \nPlease file "
1442*f6aab3d8Srobert "a bug and attach the file at the start of "
1443*f6aab3d8Srobert "this error message",
1444*f6aab3d8Srobert die.GetOffset(),
1445*f6aab3d8Srobert encoding_form.Reference().GetOffset(),
1446*f6aab3d8Srobert parent_die.GetOffset());
1447*f6aab3d8Srobert return;
1448*f6aab3d8Srobert }
1449*f6aab3d8Srobert
1450*f6aab3d8Srobert CompilerType base_class_clang_type = base_class_type->GetFullCompilerType();
1451*f6aab3d8Srobert assert(base_class_clang_type);
1452*f6aab3d8Srobert if (TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type)) {
1453*f6aab3d8Srobert ast->SetObjCSuperClass(class_clang_type, base_class_clang_type);
1454*f6aab3d8Srobert return;
1455*f6aab3d8Srobert }
1456*f6aab3d8Srobert std::unique_ptr<clang::CXXBaseSpecifier> result =
1457*f6aab3d8Srobert ast->CreateBaseClassSpecifier(base_class_clang_type.GetOpaqueQualType(),
1458*f6aab3d8Srobert accessibility, is_virtual,
1459*f6aab3d8Srobert is_base_of_class);
1460*f6aab3d8Srobert if (!result)
1461*f6aab3d8Srobert return;
1462*f6aab3d8Srobert
1463*f6aab3d8Srobert base_classes.push_back(std::move(result));
1464*f6aab3d8Srobert
1465*f6aab3d8Srobert if (is_virtual) {
1466*f6aab3d8Srobert // Do not specify any offset for virtual inheritance. The DWARF
1467*f6aab3d8Srobert // produced by clang doesn't give us a constant offset, but gives
1468*f6aab3d8Srobert // us a DWARF expressions that requires an actual object in memory.
1469*f6aab3d8Srobert // the DW_AT_data_member_location for a virtual base class looks
1470*f6aab3d8Srobert // like:
1471*f6aab3d8Srobert // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref,
1472*f6aab3d8Srobert // DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref,
1473*f6aab3d8Srobert // DW_OP_plus )
1474*f6aab3d8Srobert // Given this, there is really no valid response we can give to
1475*f6aab3d8Srobert // clang for virtual base class offsets, and this should eventually
1476*f6aab3d8Srobert // be removed from LayoutRecordType() in the external
1477*f6aab3d8Srobert // AST source in clang.
1478*f6aab3d8Srobert } else {
1479*f6aab3d8Srobert layout_info.base_offsets.insert(std::make_pair(
1480*f6aab3d8Srobert ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()),
1481*f6aab3d8Srobert clang::CharUnits::fromQuantity(member_byte_offset)));
1482*f6aab3d8Srobert }
1483*f6aab3d8Srobert }
1484*f6aab3d8Srobert
UpdateSymbolContextScopeForType(const SymbolContext & sc,const DWARFDIE & die,TypeSP type_sp)1485061da546Spatrick TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
1486061da546Spatrick const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) {
1487061da546Spatrick if (!type_sp)
1488061da546Spatrick return type_sp;
1489061da546Spatrick
1490061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
1491061da546Spatrick DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
1492061da546Spatrick dw_tag_t sc_parent_tag = sc_parent_die.Tag();
1493061da546Spatrick
1494061da546Spatrick SymbolContextScope *symbol_context_scope = nullptr;
1495061da546Spatrick if (sc_parent_tag == DW_TAG_compile_unit ||
1496061da546Spatrick sc_parent_tag == DW_TAG_partial_unit) {
1497061da546Spatrick symbol_context_scope = sc.comp_unit;
1498061da546Spatrick } else if (sc.function != nullptr && sc_parent_die) {
1499061da546Spatrick symbol_context_scope =
1500061da546Spatrick sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
1501061da546Spatrick if (symbol_context_scope == nullptr)
1502061da546Spatrick symbol_context_scope = sc.function;
1503061da546Spatrick } else {
1504061da546Spatrick symbol_context_scope = sc.module_sp.get();
1505061da546Spatrick }
1506061da546Spatrick
1507061da546Spatrick if (symbol_context_scope != nullptr)
1508061da546Spatrick type_sp->SetSymbolContextScope(symbol_context_scope);
1509061da546Spatrick
1510061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
1511061da546Spatrick return type_sp;
1512061da546Spatrick }
1513061da546Spatrick
1514*f6aab3d8Srobert std::string
GetCPlusPlusQualifiedName(const DWARFDIE & die)1515*f6aab3d8Srobert DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
1516*f6aab3d8Srobert if (!die.IsValid())
1517*f6aab3d8Srobert return "";
1518*f6aab3d8Srobert const char *name = die.GetName();
1519*f6aab3d8Srobert if (!name)
1520*f6aab3d8Srobert return "";
1521*f6aab3d8Srobert std::string qualified_name;
1522*f6aab3d8Srobert DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE();
1523*f6aab3d8Srobert // TODO: change this to get the correct decl context parent....
1524*f6aab3d8Srobert while (parent_decl_ctx_die) {
1525*f6aab3d8Srobert // The name may not contain template parameters due to
1526*f6aab3d8Srobert // -gsimple-template-names; we must reconstruct the full name from child
1527*f6aab3d8Srobert // template parameter dies via GetDIEClassTemplateParams().
1528*f6aab3d8Srobert const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();
1529*f6aab3d8Srobert switch (parent_tag) {
1530*f6aab3d8Srobert case DW_TAG_namespace: {
1531*f6aab3d8Srobert if (const char *namespace_name = parent_decl_ctx_die.GetName()) {
1532*f6aab3d8Srobert qualified_name.insert(0, "::");
1533*f6aab3d8Srobert qualified_name.insert(0, namespace_name);
1534*f6aab3d8Srobert } else {
1535*f6aab3d8Srobert qualified_name.insert(0, "(anonymous namespace)::");
1536*f6aab3d8Srobert }
1537*f6aab3d8Srobert parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
1538*f6aab3d8Srobert break;
1539*f6aab3d8Srobert }
1540*f6aab3d8Srobert
1541*f6aab3d8Srobert case DW_TAG_class_type:
1542*f6aab3d8Srobert case DW_TAG_structure_type:
1543*f6aab3d8Srobert case DW_TAG_union_type: {
1544*f6aab3d8Srobert if (const char *class_union_struct_name = parent_decl_ctx_die.GetName()) {
1545*f6aab3d8Srobert qualified_name.insert(
1546*f6aab3d8Srobert 0, GetDIEClassTemplateParams(parent_decl_ctx_die).AsCString(""));
1547*f6aab3d8Srobert qualified_name.insert(0, "::");
1548*f6aab3d8Srobert qualified_name.insert(0, class_union_struct_name);
1549*f6aab3d8Srobert }
1550*f6aab3d8Srobert parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
1551*f6aab3d8Srobert break;
1552*f6aab3d8Srobert }
1553*f6aab3d8Srobert
1554*f6aab3d8Srobert default:
1555*f6aab3d8Srobert parent_decl_ctx_die.Clear();
1556*f6aab3d8Srobert break;
1557*f6aab3d8Srobert }
1558*f6aab3d8Srobert }
1559*f6aab3d8Srobert
1560*f6aab3d8Srobert if (qualified_name.empty())
1561*f6aab3d8Srobert qualified_name.append("::");
1562*f6aab3d8Srobert
1563*f6aab3d8Srobert qualified_name.append(name);
1564*f6aab3d8Srobert qualified_name.append(GetDIEClassTemplateParams(die).AsCString(""));
1565*f6aab3d8Srobert
1566*f6aab3d8Srobert return qualified_name;
1567*f6aab3d8Srobert }
1568*f6aab3d8Srobert
1569061da546Spatrick TypeSP
ParseStructureLikeDIE(const SymbolContext & sc,const DWARFDIE & die,ParsedDWARFTypeAttributes & attrs)1570061da546Spatrick DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
1571061da546Spatrick const DWARFDIE &die,
1572061da546Spatrick ParsedDWARFTypeAttributes &attrs) {
1573061da546Spatrick TypeSP type_sp;
1574061da546Spatrick CompilerType clang_type;
1575061da546Spatrick const dw_tag_t tag = die.Tag();
1576061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
1577dda28197Spatrick LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());
1578*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
1579061da546Spatrick
1580061da546Spatrick // UniqueDWARFASTType is large, so don't create a local variables on the
1581061da546Spatrick // stack, put it on the heap. This function is often called recursively and
1582061da546Spatrick // clang isn't good at sharing the stack space for variables in different
1583061da546Spatrick // blocks.
1584061da546Spatrick auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>();
1585061da546Spatrick
1586061da546Spatrick ConstString unique_typename(attrs.name);
1587061da546Spatrick Declaration unique_decl(attrs.decl);
1588061da546Spatrick
1589061da546Spatrick if (attrs.name) {
1590061da546Spatrick if (Language::LanguageIsCPlusPlus(cu_language)) {
1591061da546Spatrick // For C++, we rely solely upon the one definition rule that says
1592061da546Spatrick // only one thing can exist at a given decl context. We ignore the
1593061da546Spatrick // file and line that things are declared on.
1594*f6aab3d8Srobert std::string qualified_name = GetCPlusPlusQualifiedName(die);
1595*f6aab3d8Srobert if (!qualified_name.empty())
1596061da546Spatrick unique_typename = ConstString(qualified_name);
1597061da546Spatrick unique_decl.Clear();
1598061da546Spatrick }
1599061da546Spatrick
1600061da546Spatrick if (dwarf->GetUniqueDWARFASTTypeMap().Find(
1601*f6aab3d8Srobert unique_typename, die, unique_decl, attrs.byte_size.value_or(-1),
1602061da546Spatrick *unique_ast_entry_up)) {
1603061da546Spatrick type_sp = unique_ast_entry_up->m_type_sp;
1604061da546Spatrick if (type_sp) {
1605061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
1606061da546Spatrick LinkDeclContextToDIE(
1607061da546Spatrick GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die);
1608061da546Spatrick return type_sp;
1609061da546Spatrick }
1610061da546Spatrick }
1611061da546Spatrick }
1612061da546Spatrick
1613061da546Spatrick DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
1614061da546Spatrick DW_TAG_value_to_name(tag), type_name_cstr);
1615061da546Spatrick
1616061da546Spatrick int tag_decl_kind = -1;
1617061da546Spatrick AccessType default_accessibility = eAccessNone;
1618061da546Spatrick if (tag == DW_TAG_structure_type) {
1619061da546Spatrick tag_decl_kind = clang::TTK_Struct;
1620061da546Spatrick default_accessibility = eAccessPublic;
1621061da546Spatrick } else if (tag == DW_TAG_union_type) {
1622061da546Spatrick tag_decl_kind = clang::TTK_Union;
1623061da546Spatrick default_accessibility = eAccessPublic;
1624061da546Spatrick } else if (tag == DW_TAG_class_type) {
1625061da546Spatrick tag_decl_kind = clang::TTK_Class;
1626061da546Spatrick default_accessibility = eAccessPrivate;
1627061da546Spatrick }
1628061da546Spatrick
1629061da546Spatrick if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
1630061da546Spatrick !die.HasChildren() && cu_language == eLanguageTypeObjC) {
1631061da546Spatrick // Work around an issue with clang at the moment where forward
1632061da546Spatrick // declarations for objective C classes are emitted as:
1633061da546Spatrick // DW_TAG_structure_type [2]
1634061da546Spatrick // DW_AT_name( "ForwardObjcClass" )
1635061da546Spatrick // DW_AT_byte_size( 0x00 )
1636061da546Spatrick // DW_AT_decl_file( "..." )
1637061da546Spatrick // DW_AT_decl_line( 1 )
1638061da546Spatrick //
1639061da546Spatrick // Note that there is no DW_AT_declaration and there are no children,
1640061da546Spatrick // and the byte size is zero.
1641061da546Spatrick attrs.is_forward_declaration = true;
1642061da546Spatrick }
1643061da546Spatrick
1644061da546Spatrick if (attrs.class_language == eLanguageTypeObjC ||
1645061da546Spatrick attrs.class_language == eLanguageTypeObjC_plus_plus) {
1646061da546Spatrick if (!attrs.is_complete_objc_class &&
1647061da546Spatrick die.Supports_DW_AT_APPLE_objc_complete_type()) {
1648061da546Spatrick // We have a valid eSymbolTypeObjCClass class symbol whose name
1649061da546Spatrick // matches the current objective C class that we are trying to find
1650061da546Spatrick // and this DIE isn't the complete definition (we checked
1651061da546Spatrick // is_complete_objc_class above and know it is false), so the real
1652061da546Spatrick // definition is in here somewhere
1653061da546Spatrick type_sp =
1654061da546Spatrick dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
1655061da546Spatrick
1656061da546Spatrick if (!type_sp) {
1657061da546Spatrick SymbolFileDWARFDebugMap *debug_map_symfile =
1658061da546Spatrick dwarf->GetDebugMapSymfile();
1659061da546Spatrick if (debug_map_symfile) {
1660061da546Spatrick // We weren't able to find a full declaration in this DWARF,
1661061da546Spatrick // see if we have a declaration anywhere else...
1662061da546Spatrick type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
1663061da546Spatrick die, attrs.name, true);
1664061da546Spatrick }
1665061da546Spatrick }
1666061da546Spatrick
1667061da546Spatrick if (type_sp) {
1668061da546Spatrick if (log) {
1669061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
1670061da546Spatrick log,
1671*f6aab3d8Srobert "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
1672*f6aab3d8Srobert "\"{3}\" is an "
1673*f6aab3d8Srobert "incomplete objc type, complete type is {4:x8}",
1674061da546Spatrick static_cast<void *>(this), die.GetOffset(),
1675061da546Spatrick DW_TAG_value_to_name(tag), attrs.name.GetCString(),
1676061da546Spatrick type_sp->GetID());
1677061da546Spatrick }
1678061da546Spatrick
1679061da546Spatrick // We found a real definition for this type elsewhere so lets use
1680061da546Spatrick // it and cache the fact that we found a complete type for this
1681061da546Spatrick // die
1682061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
1683061da546Spatrick return type_sp;
1684061da546Spatrick }
1685061da546Spatrick }
1686061da546Spatrick }
1687061da546Spatrick
1688061da546Spatrick if (attrs.is_forward_declaration) {
1689061da546Spatrick // We have a forward declaration to a type and we need to try and
1690061da546Spatrick // find a full declaration. We look in the current type index just in
1691061da546Spatrick // case we have a forward declaration followed by an actual
1692061da546Spatrick // declarations in the DWARF. If this fails, we need to look
1693061da546Spatrick // elsewhere...
1694061da546Spatrick if (log) {
1695061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
1696061da546Spatrick log,
1697*f6aab3d8Srobert "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
1698061da546Spatrick "forward declaration, trying to find complete type",
1699061da546Spatrick static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
1700061da546Spatrick attrs.name.GetCString());
1701061da546Spatrick }
1702061da546Spatrick
1703061da546Spatrick // See if the type comes from a Clang module and if so, track down
1704061da546Spatrick // that type.
1705061da546Spatrick type_sp = ParseTypeFromClangModule(sc, die, log);
1706061da546Spatrick if (type_sp)
1707061da546Spatrick return type_sp;
1708061da546Spatrick
1709061da546Spatrick // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
1710061da546Spatrick // type_name_const_str);
1711*f6aab3d8Srobert type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
1712061da546Spatrick
1713061da546Spatrick if (!type_sp) {
1714061da546Spatrick SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
1715061da546Spatrick if (debug_map_symfile) {
1716061da546Spatrick // We weren't able to find a full declaration in this DWARF, see
1717061da546Spatrick // if we have a declaration anywhere else...
1718*f6aab3d8Srobert type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
1719061da546Spatrick }
1720061da546Spatrick }
1721061da546Spatrick
1722061da546Spatrick if (type_sp) {
1723061da546Spatrick if (log) {
1724061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
1725061da546Spatrick log,
1726*f6aab3d8Srobert "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
1727*f6aab3d8Srobert "forward declaration, complete type is {4:x8}",
1728061da546Spatrick static_cast<void *>(this), die.GetOffset(),
1729061da546Spatrick DW_TAG_value_to_name(tag), attrs.name.GetCString(),
1730061da546Spatrick type_sp->GetID());
1731061da546Spatrick }
1732061da546Spatrick
1733061da546Spatrick // We found a real definition for this type elsewhere so lets use
1734061da546Spatrick // it and cache the fact that we found a complete type for this die
1735061da546Spatrick dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
1736061da546Spatrick clang::DeclContext *defn_decl_ctx =
1737061da546Spatrick GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
1738061da546Spatrick if (defn_decl_ctx)
1739061da546Spatrick LinkDeclContextToDIE(defn_decl_ctx, die);
1740061da546Spatrick return type_sp;
1741061da546Spatrick }
1742061da546Spatrick }
1743061da546Spatrick assert(tag_decl_kind != -1);
1744*f6aab3d8Srobert (void)tag_decl_kind;
1745061da546Spatrick bool clang_type_was_created = false;
1746*f6aab3d8Srobert clang_type =
1747*f6aab3d8Srobert CompilerType(m_ast.weak_from_this(),
1748*f6aab3d8Srobert dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
1749061da546Spatrick if (!clang_type) {
1750061da546Spatrick clang::DeclContext *decl_ctx =
1751061da546Spatrick GetClangDeclContextContainingDIE(die, nullptr);
1752061da546Spatrick
1753be691f3bSpatrick PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die,
1754061da546Spatrick attrs.name.GetCString());
1755061da546Spatrick
1756061da546Spatrick if (attrs.accessibility == eAccessNone && decl_ctx) {
1757061da546Spatrick // Check the decl context that contains this class/struct/union. If
1758061da546Spatrick // it is a class we must give it an accessibility.
1759061da546Spatrick const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
1760061da546Spatrick if (DeclKindIsCXXClass(containing_decl_kind))
1761061da546Spatrick attrs.accessibility = default_accessibility;
1762061da546Spatrick }
1763061da546Spatrick
1764061da546Spatrick ClangASTMetadata metadata;
1765061da546Spatrick metadata.SetUserID(die.GetID());
1766061da546Spatrick metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die));
1767061da546Spatrick
1768dda28197Spatrick TypeSystemClang::TemplateParameterInfos template_param_infos;
1769061da546Spatrick if (ParseTemplateParameterInfos(die, template_param_infos)) {
1770061da546Spatrick clang::ClassTemplateDecl *class_template_decl =
1771dda28197Spatrick m_ast.ParseClassTemplateDecl(
1772dda28197Spatrick decl_ctx, GetOwningClangModule(die), attrs.accessibility,
1773dda28197Spatrick attrs.name.GetCString(), tag_decl_kind, template_param_infos);
1774061da546Spatrick if (!class_template_decl) {
1775061da546Spatrick if (log) {
1776061da546Spatrick dwarf->GetObjectFile()->GetModule()->LogMessage(
1777061da546Spatrick log,
1778*f6aab3d8Srobert "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" "
1779061da546Spatrick "clang::ClassTemplateDecl failed to return a decl.",
1780061da546Spatrick static_cast<void *>(this), die.GetOffset(),
1781061da546Spatrick DW_TAG_value_to_name(tag), attrs.name.GetCString());
1782061da546Spatrick }
1783061da546Spatrick return TypeSP();
1784061da546Spatrick }
1785061da546Spatrick
1786061da546Spatrick clang::ClassTemplateSpecializationDecl *class_specialization_decl =
1787061da546Spatrick m_ast.CreateClassTemplateSpecializationDecl(
1788dda28197Spatrick decl_ctx, GetOwningClangModule(die), class_template_decl,
1789dda28197Spatrick tag_decl_kind, template_param_infos);
1790061da546Spatrick clang_type = m_ast.CreateClassTemplateSpecializationType(
1791061da546Spatrick class_specialization_decl);
1792061da546Spatrick clang_type_was_created = true;
1793061da546Spatrick
1794061da546Spatrick m_ast.SetMetadata(class_template_decl, metadata);
1795061da546Spatrick m_ast.SetMetadata(class_specialization_decl, metadata);
1796061da546Spatrick }
1797061da546Spatrick
1798061da546Spatrick if (!clang_type_was_created) {
1799061da546Spatrick clang_type_was_created = true;
1800061da546Spatrick clang_type = m_ast.CreateRecordType(
1801dda28197Spatrick decl_ctx, GetOwningClangModule(die), attrs.accessibility,
1802dda28197Spatrick attrs.name.GetCString(), tag_decl_kind, attrs.class_language,
1803dda28197Spatrick &metadata, attrs.exports_symbols);
1804061da546Spatrick }
1805061da546Spatrick }
1806061da546Spatrick
1807061da546Spatrick // Store a forward declaration to this class type in case any
1808061da546Spatrick // parameters in any class methods need it for the clang types for
1809061da546Spatrick // function prototypes.
1810061da546Spatrick LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
1811*f6aab3d8Srobert type_sp = dwarf->MakeType(
1812*f6aab3d8Srobert die.GetID(), attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID,
1813*f6aab3d8Srobert Type::eEncodingIsUID, &attrs.decl, clang_type,
1814dda28197Spatrick Type::ResolveState::Forward,
1815dda28197Spatrick TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class));
1816061da546Spatrick
1817061da546Spatrick // Add our type to the unique type map so we don't end up creating many
1818061da546Spatrick // copies of the same type over and over in the ASTContext for our
1819061da546Spatrick // module
1820061da546Spatrick unique_ast_entry_up->m_type_sp = type_sp;
1821061da546Spatrick unique_ast_entry_up->m_die = die;
1822061da546Spatrick unique_ast_entry_up->m_declaration = unique_decl;
1823*f6aab3d8Srobert unique_ast_entry_up->m_byte_size = attrs.byte_size.value_or(0);
1824061da546Spatrick dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
1825061da546Spatrick *unique_ast_entry_up);
1826061da546Spatrick
1827061da546Spatrick if (!attrs.is_forward_declaration) {
1828061da546Spatrick // Always start the definition for a class type so that if the class
1829061da546Spatrick // has child classes or types that require the class to be created
1830061da546Spatrick // for use as their decl contexts the class will be ready to accept
1831061da546Spatrick // these child definitions.
1832061da546Spatrick if (!die.HasChildren()) {
1833061da546Spatrick // No children for this struct/union/class, lets finish it
1834dda28197Spatrick if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) {
1835dda28197Spatrick TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);
1836061da546Spatrick } else {
1837061da546Spatrick dwarf->GetObjectFile()->GetModule()->ReportError(
1838*f6aab3d8Srobert
1839*f6aab3d8Srobert "DWARF DIE at {0:x16} named \"{1}\" was not able to start "
1840*f6aab3d8Srobert "its "
1841061da546Spatrick "definition.\nPlease file a bug and attach the file at the "
1842061da546Spatrick "start of this error message",
1843061da546Spatrick die.GetOffset(), attrs.name.GetCString());
1844061da546Spatrick }
1845061da546Spatrick
1846be691f3bSpatrick // If the byte size of the record is specified then overwrite the size
1847be691f3bSpatrick // that would be computed by Clang. This is only needed as LLDB's
1848be691f3bSpatrick // TypeSystemClang is always in C++ mode, but some compilers such as
1849be691f3bSpatrick // GCC and Clang give empty structs a size of 0 in C mode (in contrast to
1850be691f3bSpatrick // the size of 1 for empty structs that would be computed in C++ mode).
1851be691f3bSpatrick if (attrs.byte_size) {
1852061da546Spatrick clang::RecordDecl *record_decl =
1853dda28197Spatrick TypeSystemClang::GetAsRecordDecl(clang_type);
1854061da546Spatrick if (record_decl) {
1855be691f3bSpatrick ClangASTImporter::LayoutInfo layout;
1856be691f3bSpatrick layout.bit_size = *attrs.byte_size * 8;
1857be691f3bSpatrick GetClangASTImporter().SetRecordLayout(record_decl, layout);
1858061da546Spatrick }
1859061da546Spatrick }
1860061da546Spatrick } else if (clang_type_was_created) {
1861061da546Spatrick // Start the definition if the class is not objective C since the
1862061da546Spatrick // underlying decls respond to isCompleteDefinition(). Objective
1863061da546Spatrick // C decls don't respond to isCompleteDefinition() so we can't
1864061da546Spatrick // start the declaration definition right away. For C++
1865061da546Spatrick // class/union/structs we want to start the definition in case the
1866061da546Spatrick // class is needed as the declaration context for a contained class
1867061da546Spatrick // or type without the need to complete that type..
1868061da546Spatrick
1869061da546Spatrick if (attrs.class_language != eLanguageTypeObjC &&
1870061da546Spatrick attrs.class_language != eLanguageTypeObjC_plus_plus)
1871dda28197Spatrick TypeSystemClang::StartTagDeclarationDefinition(clang_type);
1872061da546Spatrick
1873061da546Spatrick // Leave this as a forward declaration until we need to know the
1874061da546Spatrick // details of the type. lldb_private::Type will automatically call
1875061da546Spatrick // the SymbolFile virtual function
1876061da546Spatrick // "SymbolFileDWARF::CompleteType(Type *)" When the definition
1877061da546Spatrick // needs to be defined.
1878061da546Spatrick assert(!dwarf->GetForwardDeclClangTypeToDie().count(
1879061da546Spatrick ClangUtil::RemoveFastQualifiers(clang_type)
1880061da546Spatrick .GetOpaqueQualType()) &&
1881061da546Spatrick "Type already in the forward declaration map!");
1882061da546Spatrick // Can't assume m_ast.GetSymbolFile() is actually a
1883061da546Spatrick // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple
1884061da546Spatrick // binaries.
1885061da546Spatrick dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] =
1886061da546Spatrick clang_type.GetOpaqueQualType();
1887dda28197Spatrick dwarf->GetForwardDeclClangTypeToDie().try_emplace(
1888dda28197Spatrick ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),
1889dda28197Spatrick *die.GetDIERef());
1890061da546Spatrick m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
1891061da546Spatrick }
1892061da546Spatrick }
1893061da546Spatrick
1894061da546Spatrick // If we made a clang type, set the trivial abi if applicable: We only
1895061da546Spatrick // do this for pass by value - which implies the Trivial ABI. There
1896061da546Spatrick // isn't a way to assert that something that would normally be pass by
1897061da546Spatrick // value is pass by reference, so we ignore that attribute if set.
1898061da546Spatrick if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
1899061da546Spatrick clang::CXXRecordDecl *record_decl =
1900061da546Spatrick m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
1901061da546Spatrick if (record_decl && record_decl->getDefinition()) {
1902061da546Spatrick record_decl->setHasTrivialSpecialMemberForCall();
1903061da546Spatrick }
1904061da546Spatrick }
1905061da546Spatrick
1906061da546Spatrick if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) {
1907061da546Spatrick clang::CXXRecordDecl *record_decl =
1908061da546Spatrick m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
1909061da546Spatrick if (record_decl)
1910061da546Spatrick record_decl->setArgPassingRestrictions(
1911061da546Spatrick clang::RecordDecl::APK_CannotPassInRegs);
1912061da546Spatrick }
1913061da546Spatrick return type_sp;
1914061da546Spatrick }
1915061da546Spatrick
1916061da546Spatrick // DWARF parsing functions
1917061da546Spatrick
1918061da546Spatrick class DWARFASTParserClang::DelayedAddObjCClassProperty {
1919061da546Spatrick public:
DelayedAddObjCClassProperty(const CompilerType & class_opaque_type,const char * property_name,const CompilerType & property_opaque_type,const char * property_setter_name,const char * property_getter_name,uint32_t property_attributes,const ClangASTMetadata * metadata)1920061da546Spatrick DelayedAddObjCClassProperty(
1921061da546Spatrick const CompilerType &class_opaque_type, const char *property_name,
1922061da546Spatrick const CompilerType &property_opaque_type, // The property type is only
1923061da546Spatrick // required if you don't have an
1924061da546Spatrick // ivar decl
1925*f6aab3d8Srobert const char *property_setter_name, const char *property_getter_name,
1926*f6aab3d8Srobert uint32_t property_attributes, const ClangASTMetadata *metadata)
1927061da546Spatrick : m_class_opaque_type(class_opaque_type), m_property_name(property_name),
1928*f6aab3d8Srobert m_property_opaque_type(property_opaque_type),
1929061da546Spatrick m_property_setter_name(property_setter_name),
1930061da546Spatrick m_property_getter_name(property_getter_name),
1931061da546Spatrick m_property_attributes(property_attributes) {
1932061da546Spatrick if (metadata != nullptr) {
1933dda28197Spatrick m_metadata_up = std::make_unique<ClangASTMetadata>();
1934061da546Spatrick *m_metadata_up = *metadata;
1935061da546Spatrick }
1936061da546Spatrick }
1937061da546Spatrick
DelayedAddObjCClassProperty(const DelayedAddObjCClassProperty & rhs)1938061da546Spatrick DelayedAddObjCClassProperty(const DelayedAddObjCClassProperty &rhs) {
1939061da546Spatrick *this = rhs;
1940061da546Spatrick }
1941061da546Spatrick
1942061da546Spatrick DelayedAddObjCClassProperty &
operator =(const DelayedAddObjCClassProperty & rhs)1943061da546Spatrick operator=(const DelayedAddObjCClassProperty &rhs) {
1944061da546Spatrick m_class_opaque_type = rhs.m_class_opaque_type;
1945061da546Spatrick m_property_name = rhs.m_property_name;
1946061da546Spatrick m_property_opaque_type = rhs.m_property_opaque_type;
1947061da546Spatrick m_property_setter_name = rhs.m_property_setter_name;
1948061da546Spatrick m_property_getter_name = rhs.m_property_getter_name;
1949061da546Spatrick m_property_attributes = rhs.m_property_attributes;
1950061da546Spatrick
1951061da546Spatrick if (rhs.m_metadata_up) {
1952dda28197Spatrick m_metadata_up = std::make_unique<ClangASTMetadata>();
1953061da546Spatrick *m_metadata_up = *rhs.m_metadata_up;
1954061da546Spatrick }
1955061da546Spatrick return *this;
1956061da546Spatrick }
1957061da546Spatrick
Finalize()1958061da546Spatrick bool Finalize() {
1959dda28197Spatrick return TypeSystemClang::AddObjCClassProperty(
1960061da546Spatrick m_class_opaque_type, m_property_name, m_property_opaque_type,
1961*f6aab3d8Srobert /*ivar_decl=*/nullptr, m_property_setter_name, m_property_getter_name,
1962061da546Spatrick m_property_attributes, m_metadata_up.get());
1963061da546Spatrick }
1964061da546Spatrick
1965061da546Spatrick private:
1966061da546Spatrick CompilerType m_class_opaque_type;
1967061da546Spatrick const char *m_property_name;
1968061da546Spatrick CompilerType m_property_opaque_type;
1969061da546Spatrick const char *m_property_setter_name;
1970061da546Spatrick const char *m_property_getter_name;
1971061da546Spatrick uint32_t m_property_attributes;
1972061da546Spatrick std::unique_ptr<ClangASTMetadata> m_metadata_up;
1973061da546Spatrick };
1974061da546Spatrick
ParseTemplateDIE(const DWARFDIE & die,TypeSystemClang::TemplateParameterInfos & template_param_infos)1975061da546Spatrick bool DWARFASTParserClang::ParseTemplateDIE(
1976061da546Spatrick const DWARFDIE &die,
1977dda28197Spatrick TypeSystemClang::TemplateParameterInfos &template_param_infos) {
1978061da546Spatrick const dw_tag_t tag = die.Tag();
1979061da546Spatrick bool is_template_template_argument = false;
1980061da546Spatrick
1981061da546Spatrick switch (tag) {
1982061da546Spatrick case DW_TAG_GNU_template_parameter_pack: {
1983dda28197Spatrick template_param_infos.packed_args =
1984dda28197Spatrick std::make_unique<TypeSystemClang::TemplateParameterInfos>();
1985be691f3bSpatrick for (DWARFDIE child_die : die.children()) {
1986061da546Spatrick if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args))
1987061da546Spatrick return false;
1988061da546Spatrick }
1989061da546Spatrick if (const char *name = die.GetName()) {
1990061da546Spatrick template_param_infos.pack_name = name;
1991061da546Spatrick }
1992061da546Spatrick return true;
1993061da546Spatrick }
1994061da546Spatrick case DW_TAG_GNU_template_template_param:
1995061da546Spatrick is_template_template_argument = true;
1996*f6aab3d8Srobert [[fallthrough]];
1997061da546Spatrick case DW_TAG_template_type_parameter:
1998061da546Spatrick case DW_TAG_template_value_parameter: {
1999061da546Spatrick DWARFAttributes attributes;
2000061da546Spatrick const size_t num_attributes = die.GetAttributes(attributes);
2001061da546Spatrick const char *name = nullptr;
2002061da546Spatrick const char *template_name = nullptr;
2003061da546Spatrick CompilerType clang_type;
2004061da546Spatrick uint64_t uval64 = 0;
2005061da546Spatrick bool uval64_valid = false;
2006061da546Spatrick if (num_attributes > 0) {
2007061da546Spatrick DWARFFormValue form_value;
2008061da546Spatrick for (size_t i = 0; i < num_attributes; ++i) {
2009061da546Spatrick const dw_attr_t attr = attributes.AttributeAtIndex(i);
2010061da546Spatrick
2011061da546Spatrick switch (attr) {
2012061da546Spatrick case DW_AT_name:
2013061da546Spatrick if (attributes.ExtractFormValueAtIndex(i, form_value))
2014061da546Spatrick name = form_value.AsCString();
2015061da546Spatrick break;
2016061da546Spatrick
2017061da546Spatrick case DW_AT_GNU_template_name:
2018061da546Spatrick if (attributes.ExtractFormValueAtIndex(i, form_value))
2019061da546Spatrick template_name = form_value.AsCString();
2020061da546Spatrick break;
2021061da546Spatrick
2022061da546Spatrick case DW_AT_type:
2023061da546Spatrick if (attributes.ExtractFormValueAtIndex(i, form_value)) {
2024061da546Spatrick Type *lldb_type = die.ResolveTypeUID(form_value.Reference());
2025061da546Spatrick if (lldb_type)
2026061da546Spatrick clang_type = lldb_type->GetForwardCompilerType();
2027061da546Spatrick }
2028061da546Spatrick break;
2029061da546Spatrick
2030061da546Spatrick case DW_AT_const_value:
2031061da546Spatrick if (attributes.ExtractFormValueAtIndex(i, form_value)) {
2032061da546Spatrick uval64_valid = true;
2033061da546Spatrick uval64 = form_value.Unsigned();
2034061da546Spatrick }
2035061da546Spatrick break;
2036061da546Spatrick default:
2037061da546Spatrick break;
2038061da546Spatrick }
2039061da546Spatrick }
2040061da546Spatrick
2041061da546Spatrick clang::ASTContext &ast = m_ast.getASTContext();
2042061da546Spatrick if (!clang_type)
2043061da546Spatrick clang_type = m_ast.GetBasicType(eBasicTypeVoid);
2044061da546Spatrick
2045061da546Spatrick if (!is_template_template_argument) {
2046061da546Spatrick bool is_signed = false;
2047061da546Spatrick if (name && name[0])
2048061da546Spatrick template_param_infos.names.push_back(name);
2049061da546Spatrick else
2050*f6aab3d8Srobert template_param_infos.names.push_back(nullptr);
2051061da546Spatrick
2052061da546Spatrick // Get the signed value for any integer or enumeration if available
2053061da546Spatrick clang_type.IsIntegerOrEnumerationType(is_signed);
2054061da546Spatrick
2055061da546Spatrick if (tag == DW_TAG_template_value_parameter && uval64_valid) {
2056*f6aab3d8Srobert std::optional<uint64_t> size = clang_type.GetBitSize(nullptr);
2057061da546Spatrick if (!size)
2058061da546Spatrick return false;
2059061da546Spatrick llvm::APInt apint(*size, uval64, is_signed);
2060061da546Spatrick template_param_infos.args.push_back(
2061061da546Spatrick clang::TemplateArgument(ast, llvm::APSInt(apint, !is_signed),
2062061da546Spatrick ClangUtil::GetQualType(clang_type)));
2063061da546Spatrick } else {
2064061da546Spatrick template_param_infos.args.push_back(
2065061da546Spatrick clang::TemplateArgument(ClangUtil::GetQualType(clang_type)));
2066061da546Spatrick }
2067061da546Spatrick } else {
2068061da546Spatrick auto *tplt_type = m_ast.CreateTemplateTemplateParmDecl(template_name);
2069061da546Spatrick template_param_infos.names.push_back(name);
2070061da546Spatrick template_param_infos.args.push_back(
2071061da546Spatrick clang::TemplateArgument(clang::TemplateName(tplt_type)));
2072061da546Spatrick }
2073061da546Spatrick }
2074061da546Spatrick }
2075061da546Spatrick return true;
2076061da546Spatrick
2077061da546Spatrick default:
2078061da546Spatrick break;
2079061da546Spatrick }
2080061da546Spatrick return false;
2081061da546Spatrick }
2082061da546Spatrick
ParseTemplateParameterInfos(const DWARFDIE & parent_die,TypeSystemClang::TemplateParameterInfos & template_param_infos)2083061da546Spatrick bool DWARFASTParserClang::ParseTemplateParameterInfos(
2084061da546Spatrick const DWARFDIE &parent_die,
2085dda28197Spatrick TypeSystemClang::TemplateParameterInfos &template_param_infos) {
2086061da546Spatrick
2087061da546Spatrick if (!parent_die)
2088061da546Spatrick return false;
2089061da546Spatrick
2090be691f3bSpatrick for (DWARFDIE die : parent_die.children()) {
2091061da546Spatrick const dw_tag_t tag = die.Tag();
2092061da546Spatrick
2093061da546Spatrick switch (tag) {
2094061da546Spatrick case DW_TAG_template_type_parameter:
2095061da546Spatrick case DW_TAG_template_value_parameter:
2096061da546Spatrick case DW_TAG_GNU_template_parameter_pack:
2097061da546Spatrick case DW_TAG_GNU_template_template_param:
2098061da546Spatrick ParseTemplateDIE(die, template_param_infos);
2099061da546Spatrick break;
2100061da546Spatrick
2101061da546Spatrick default:
2102061da546Spatrick break;
2103061da546Spatrick }
2104061da546Spatrick }
2105*f6aab3d8Srobert return template_param_infos.args.size() ==
2106*f6aab3d8Srobert template_param_infos.names.size() &&
2107*f6aab3d8Srobert (!template_param_infos.args.empty() ||
2108*f6aab3d8Srobert template_param_infos.packed_args);
2109061da546Spatrick }
2110061da546Spatrick
CompleteRecordType(const DWARFDIE & die,lldb_private::Type * type,CompilerType & clang_type)2111061da546Spatrick bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
2112061da546Spatrick lldb_private::Type *type,
2113061da546Spatrick CompilerType &clang_type) {
2114061da546Spatrick const dw_tag_t tag = die.Tag();
2115061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
2116061da546Spatrick
2117061da546Spatrick ClangASTImporter::LayoutInfo layout_info;
2118061da546Spatrick
2119061da546Spatrick if (die.HasChildren()) {
2120dda28197Spatrick const bool type_is_objc_object_or_interface =
2121dda28197Spatrick TypeSystemClang::IsObjCObjectOrInterfaceType(clang_type);
2122dda28197Spatrick if (type_is_objc_object_or_interface) {
2123061da546Spatrick // For objective C we don't start the definition when the class is
2124061da546Spatrick // created.
2125dda28197Spatrick TypeSystemClang::StartTagDeclarationDefinition(clang_type);
2126061da546Spatrick }
2127061da546Spatrick
2128061da546Spatrick AccessType default_accessibility = eAccessNone;
2129061da546Spatrick if (tag == DW_TAG_structure_type) {
2130061da546Spatrick default_accessibility = eAccessPublic;
2131061da546Spatrick } else if (tag == DW_TAG_union_type) {
2132061da546Spatrick default_accessibility = eAccessPublic;
2133061da546Spatrick } else if (tag == DW_TAG_class_type) {
2134061da546Spatrick default_accessibility = eAccessPrivate;
2135061da546Spatrick }
2136061da546Spatrick
2137061da546Spatrick std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
2138061da546Spatrick // Parse members and base classes first
2139061da546Spatrick std::vector<DWARFDIE> member_function_dies;
2140061da546Spatrick
2141061da546Spatrick DelayedPropertyList delayed_properties;
2142be691f3bSpatrick ParseChildMembers(die, clang_type, bases, member_function_dies,
2143be691f3bSpatrick delayed_properties, default_accessibility, layout_info);
2144061da546Spatrick
2145061da546Spatrick // Now parse any methods if there were any...
2146061da546Spatrick for (const DWARFDIE &die : member_function_dies)
2147061da546Spatrick dwarf->ResolveType(die);
2148061da546Spatrick
2149dda28197Spatrick if (type_is_objc_object_or_interface) {
2150061da546Spatrick ConstString class_name(clang_type.GetTypeName());
2151061da546Spatrick if (class_name) {
2152dda28197Spatrick dwarf->GetObjCMethods(class_name, [&](DWARFDIE method_die) {
2153061da546Spatrick method_die.ResolveType();
2154dda28197Spatrick return true;
2155dda28197Spatrick });
2156061da546Spatrick
2157*f6aab3d8Srobert for (DelayedAddObjCClassProperty &property : delayed_properties)
2158*f6aab3d8Srobert property.Finalize();
2159061da546Spatrick }
2160061da546Spatrick }
2161061da546Spatrick
2162061da546Spatrick if (!bases.empty()) {
2163061da546Spatrick // Make sure all base classes refer to complete types and not forward
2164061da546Spatrick // declarations. If we don't do this, clang will crash with an
2165061da546Spatrick // assertion in the call to clang_type.TransferBaseClasses()
2166061da546Spatrick for (const auto &base_class : bases) {
2167061da546Spatrick clang::TypeSourceInfo *type_source_info =
2168061da546Spatrick base_class->getTypeSourceInfo();
2169dda28197Spatrick if (type_source_info)
2170*f6aab3d8Srobert TypeSystemClang::RequireCompleteType(
2171*f6aab3d8Srobert m_ast.GetType(type_source_info->getType()));
2172061da546Spatrick }
2173061da546Spatrick
2174061da546Spatrick m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
2175061da546Spatrick std::move(bases));
2176061da546Spatrick }
2177061da546Spatrick }
2178061da546Spatrick
2179061da546Spatrick m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());
2180dda28197Spatrick TypeSystemClang::BuildIndirectFields(clang_type);
2181dda28197Spatrick TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);
2182061da546Spatrick
2183061da546Spatrick if (!layout_info.field_offsets.empty() || !layout_info.base_offsets.empty() ||
2184061da546Spatrick !layout_info.vbase_offsets.empty()) {
2185061da546Spatrick if (type)
2186*f6aab3d8Srobert layout_info.bit_size = type->GetByteSize(nullptr).value_or(0) * 8;
2187061da546Spatrick if (layout_info.bit_size == 0)
2188061da546Spatrick layout_info.bit_size =
2189061da546Spatrick die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
2190061da546Spatrick
2191061da546Spatrick clang::CXXRecordDecl *record_decl =
2192061da546Spatrick m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
2193061da546Spatrick if (record_decl)
2194061da546Spatrick GetClangASTImporter().SetRecordLayout(record_decl, layout_info);
2195061da546Spatrick }
2196061da546Spatrick
2197061da546Spatrick return (bool)clang_type;
2198061da546Spatrick }
2199061da546Spatrick
CompleteEnumType(const DWARFDIE & die,lldb_private::Type * type,CompilerType & clang_type)2200061da546Spatrick bool DWARFASTParserClang::CompleteEnumType(const DWARFDIE &die,
2201061da546Spatrick lldb_private::Type *type,
2202061da546Spatrick CompilerType &clang_type) {
2203dda28197Spatrick if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) {
2204061da546Spatrick if (die.HasChildren()) {
2205061da546Spatrick bool is_signed = false;
2206061da546Spatrick clang_type.IsIntegerType(is_signed);
2207061da546Spatrick ParseChildEnumerators(clang_type, is_signed,
2208*f6aab3d8Srobert type->GetByteSize(nullptr).value_or(0), die);
2209061da546Spatrick }
2210dda28197Spatrick TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);
2211061da546Spatrick }
2212061da546Spatrick return (bool)clang_type;
2213061da546Spatrick }
2214061da546Spatrick
CompleteTypeFromDWARF(const DWARFDIE & die,lldb_private::Type * type,CompilerType & clang_type)2215061da546Spatrick bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
2216061da546Spatrick lldb_private::Type *type,
2217061da546Spatrick CompilerType &clang_type) {
2218061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
2219061da546Spatrick
2220061da546Spatrick std::lock_guard<std::recursive_mutex> guard(
2221061da546Spatrick dwarf->GetObjectFile()->GetModule()->GetMutex());
2222061da546Spatrick
2223061da546Spatrick // Disable external storage for this type so we don't get anymore
2224061da546Spatrick // clang::ExternalASTSource queries for this type.
2225061da546Spatrick m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), false);
2226061da546Spatrick
2227061da546Spatrick if (!die)
2228061da546Spatrick return false;
2229061da546Spatrick
2230061da546Spatrick const dw_tag_t tag = die.Tag();
2231061da546Spatrick
2232061da546Spatrick assert(clang_type);
2233061da546Spatrick DWARFAttributes attributes;
2234061da546Spatrick switch (tag) {
2235061da546Spatrick case DW_TAG_structure_type:
2236061da546Spatrick case DW_TAG_union_type:
2237061da546Spatrick case DW_TAG_class_type:
2238061da546Spatrick return CompleteRecordType(die, type, clang_type);
2239061da546Spatrick case DW_TAG_enumeration_type:
2240061da546Spatrick return CompleteEnumType(die, type, clang_type);
2241061da546Spatrick default:
2242061da546Spatrick assert(false && "not a forward clang type decl!");
2243061da546Spatrick break;
2244061da546Spatrick }
2245061da546Spatrick
2246061da546Spatrick return false;
2247061da546Spatrick }
2248061da546Spatrick
EnsureAllDIEsInDeclContextHaveBeenParsed(lldb_private::CompilerDeclContext decl_context)2249061da546Spatrick void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed(
2250061da546Spatrick lldb_private::CompilerDeclContext decl_context) {
2251061da546Spatrick auto opaque_decl_ctx =
2252061da546Spatrick (clang::DeclContext *)decl_context.GetOpaqueDeclContext();
2253061da546Spatrick for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx);
2254061da546Spatrick it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx;
2255061da546Spatrick it = m_decl_ctx_to_die.erase(it))
2256be691f3bSpatrick for (DWARFDIE decl : it->second.children())
2257061da546Spatrick GetClangDeclForDIE(decl);
2258061da546Spatrick }
2259061da546Spatrick
GetDeclForUIDFromDWARF(const DWARFDIE & die)2260061da546Spatrick CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) {
2261061da546Spatrick clang::Decl *clang_decl = GetClangDeclForDIE(die);
2262061da546Spatrick if (clang_decl != nullptr)
2263dda28197Spatrick return m_ast.GetCompilerDecl(clang_decl);
2264061da546Spatrick return CompilerDecl();
2265061da546Spatrick }
2266061da546Spatrick
2267061da546Spatrick CompilerDeclContext
GetDeclContextForUIDFromDWARF(const DWARFDIE & die)2268061da546Spatrick DWARFASTParserClang::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
2269061da546Spatrick clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE(die);
2270061da546Spatrick if (clang_decl_ctx)
2271061da546Spatrick return m_ast.CreateDeclContext(clang_decl_ctx);
2272061da546Spatrick return CompilerDeclContext();
2273061da546Spatrick }
2274061da546Spatrick
2275061da546Spatrick CompilerDeclContext
GetDeclContextContainingUIDFromDWARF(const DWARFDIE & die)2276061da546Spatrick DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
2277061da546Spatrick clang::DeclContext *clang_decl_ctx =
2278061da546Spatrick GetClangDeclContextContainingDIE(die, nullptr);
2279061da546Spatrick if (clang_decl_ctx)
2280061da546Spatrick return m_ast.CreateDeclContext(clang_decl_ctx);
2281061da546Spatrick return CompilerDeclContext();
2282061da546Spatrick }
2283061da546Spatrick
ParseChildEnumerators(lldb_private::CompilerType & clang_type,bool is_signed,uint32_t enumerator_byte_size,const DWARFDIE & parent_die)2284061da546Spatrick size_t DWARFASTParserClang::ParseChildEnumerators(
2285061da546Spatrick lldb_private::CompilerType &clang_type, bool is_signed,
2286061da546Spatrick uint32_t enumerator_byte_size, const DWARFDIE &parent_die) {
2287061da546Spatrick if (!parent_die)
2288061da546Spatrick return 0;
2289061da546Spatrick
2290061da546Spatrick size_t enumerators_added = 0;
2291061da546Spatrick
2292be691f3bSpatrick for (DWARFDIE die : parent_die.children()) {
2293061da546Spatrick const dw_tag_t tag = die.Tag();
2294061da546Spatrick if (tag == DW_TAG_enumerator) {
2295061da546Spatrick DWARFAttributes attributes;
2296061da546Spatrick const size_t num_child_attributes = die.GetAttributes(attributes);
2297061da546Spatrick if (num_child_attributes > 0) {
2298061da546Spatrick const char *name = nullptr;
2299061da546Spatrick bool got_value = false;
2300061da546Spatrick int64_t enum_value = 0;
2301061da546Spatrick Declaration decl;
2302061da546Spatrick
2303061da546Spatrick uint32_t i;
2304061da546Spatrick for (i = 0; i < num_child_attributes; ++i) {
2305061da546Spatrick const dw_attr_t attr = attributes.AttributeAtIndex(i);
2306061da546Spatrick DWARFFormValue form_value;
2307061da546Spatrick if (attributes.ExtractFormValueAtIndex(i, form_value)) {
2308061da546Spatrick switch (attr) {
2309061da546Spatrick case DW_AT_const_value:
2310061da546Spatrick got_value = true;
2311061da546Spatrick if (is_signed)
2312061da546Spatrick enum_value = form_value.Signed();
2313061da546Spatrick else
2314061da546Spatrick enum_value = form_value.Unsigned();
2315061da546Spatrick break;
2316061da546Spatrick
2317061da546Spatrick case DW_AT_name:
2318061da546Spatrick name = form_value.AsCString();
2319061da546Spatrick break;
2320061da546Spatrick
2321061da546Spatrick case DW_AT_description:
2322061da546Spatrick default:
2323061da546Spatrick case DW_AT_decl_file:
2324be691f3bSpatrick decl.SetFile(attributes.CompileUnitAtIndex(i)->GetFile(
2325be691f3bSpatrick form_value.Unsigned()));
2326061da546Spatrick break;
2327061da546Spatrick case DW_AT_decl_line:
2328061da546Spatrick decl.SetLine(form_value.Unsigned());
2329061da546Spatrick break;
2330061da546Spatrick case DW_AT_decl_column:
2331061da546Spatrick decl.SetColumn(form_value.Unsigned());
2332061da546Spatrick break;
2333061da546Spatrick case DW_AT_sibling:
2334061da546Spatrick break;
2335061da546Spatrick }
2336061da546Spatrick }
2337061da546Spatrick }
2338061da546Spatrick
2339061da546Spatrick if (name && name[0] && got_value) {
2340061da546Spatrick m_ast.AddEnumerationValueToEnumerationType(
2341061da546Spatrick clang_type, decl, name, enum_value, enumerator_byte_size * 8);
2342061da546Spatrick ++enumerators_added;
2343061da546Spatrick }
2344061da546Spatrick }
2345061da546Spatrick }
2346061da546Spatrick }
2347061da546Spatrick return enumerators_added;
2348061da546Spatrick }
2349061da546Spatrick
2350*f6aab3d8Srobert ConstString
ConstructDemangledNameFromDWARF(const DWARFDIE & die)2351*f6aab3d8Srobert DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
2352061da546Spatrick bool is_static = false;
2353061da546Spatrick bool is_variadic = false;
2354061da546Spatrick bool has_template_params = false;
2355061da546Spatrick unsigned type_quals = 0;
2356061da546Spatrick std::vector<CompilerType> param_types;
2357061da546Spatrick std::vector<clang::ParmVarDecl *> param_decls;
2358061da546Spatrick StreamString sstr;
2359061da546Spatrick
2360dda28197Spatrick DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die);
2361061da546Spatrick sstr << decl_ctx.GetQualifiedName();
2362061da546Spatrick
2363061da546Spatrick clang::DeclContext *containing_decl_ctx =
2364061da546Spatrick GetClangDeclContextContainingDIE(die, nullptr);
2365*f6aab3d8Srobert ParseChildParameters(containing_decl_ctx, die, true, is_static, is_variadic,
2366*f6aab3d8Srobert has_template_params, param_types, param_decls,
2367*f6aab3d8Srobert type_quals);
2368061da546Spatrick sstr << "(";
2369061da546Spatrick for (size_t i = 0; i < param_types.size(); i++) {
2370061da546Spatrick if (i > 0)
2371061da546Spatrick sstr << ", ";
2372061da546Spatrick sstr << param_types[i].GetTypeName();
2373061da546Spatrick }
2374061da546Spatrick if (is_variadic)
2375061da546Spatrick sstr << ", ...";
2376061da546Spatrick sstr << ")";
2377061da546Spatrick if (type_quals & clang::Qualifiers::Const)
2378061da546Spatrick sstr << " const";
2379061da546Spatrick
2380*f6aab3d8Srobert return ConstString(sstr.GetString());
2381*f6aab3d8Srobert }
2382*f6aab3d8Srobert
2383*f6aab3d8Srobert Function *
ParseFunctionFromDWARF(CompileUnit & comp_unit,const DWARFDIE & die,const AddressRange & func_range)2384*f6aab3d8Srobert DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
2385*f6aab3d8Srobert const DWARFDIE &die,
2386*f6aab3d8Srobert const AddressRange &func_range) {
2387*f6aab3d8Srobert assert(func_range.GetBaseAddress().IsValid());
2388*f6aab3d8Srobert DWARFRangeList func_ranges;
2389*f6aab3d8Srobert const char *name = nullptr;
2390*f6aab3d8Srobert const char *mangled = nullptr;
2391*f6aab3d8Srobert int decl_file = 0;
2392*f6aab3d8Srobert int decl_line = 0;
2393*f6aab3d8Srobert int decl_column = 0;
2394*f6aab3d8Srobert int call_file = 0;
2395*f6aab3d8Srobert int call_line = 0;
2396*f6aab3d8Srobert int call_column = 0;
2397*f6aab3d8Srobert DWARFExpressionList frame_base;
2398*f6aab3d8Srobert
2399*f6aab3d8Srobert const dw_tag_t tag = die.Tag();
2400*f6aab3d8Srobert
2401*f6aab3d8Srobert if (tag != DW_TAG_subprogram)
2402*f6aab3d8Srobert return nullptr;
2403*f6aab3d8Srobert
2404*f6aab3d8Srobert if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
2405*f6aab3d8Srobert decl_column, call_file, call_line, call_column,
2406*f6aab3d8Srobert &frame_base)) {
2407*f6aab3d8Srobert Mangled func_name;
2408*f6aab3d8Srobert if (mangled)
2409*f6aab3d8Srobert func_name.SetValue(ConstString(mangled), true);
2410*f6aab3d8Srobert else if ((die.GetParent().Tag() == DW_TAG_compile_unit ||
2411*f6aab3d8Srobert die.GetParent().Tag() == DW_TAG_partial_unit) &&
2412*f6aab3d8Srobert Language::LanguageIsCPlusPlus(
2413*f6aab3d8Srobert SymbolFileDWARF::GetLanguage(*die.GetCU())) &&
2414*f6aab3d8Srobert !Language::LanguageIsObjC(
2415*f6aab3d8Srobert SymbolFileDWARF::GetLanguage(*die.GetCU())) &&
2416*f6aab3d8Srobert name && strcmp(name, "main") != 0) {
2417*f6aab3d8Srobert // If the mangled name is not present in the DWARF, generate the
2418*f6aab3d8Srobert // demangled name using the decl context. We skip if the function is
2419*f6aab3d8Srobert // "main" as its name is never mangled.
2420*f6aab3d8Srobert func_name.SetValue(ConstructDemangledNameFromDWARF(die), false);
2421061da546Spatrick } else
2422061da546Spatrick func_name.SetValue(ConstString(name), false);
2423061da546Spatrick
2424061da546Spatrick FunctionSP func_sp;
2425061da546Spatrick std::unique_ptr<Declaration> decl_up;
2426061da546Spatrick if (decl_file != 0 || decl_line != 0 || decl_column != 0)
2427dda28197Spatrick decl_up = std::make_unique<Declaration>(die.GetCU()->GetFile(decl_file),
2428dda28197Spatrick decl_line, decl_column);
2429061da546Spatrick
2430061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
2431061da546Spatrick // Supply the type _only_ if it has already been parsed
2432061da546Spatrick Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE());
2433061da546Spatrick
2434061da546Spatrick assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
2435061da546Spatrick
2436061da546Spatrick const user_id_t func_user_id = die.GetID();
2437061da546Spatrick func_sp =
2438061da546Spatrick std::make_shared<Function>(&comp_unit,
2439061da546Spatrick func_user_id, // UserID is the DIE offset
2440061da546Spatrick func_user_id, func_name, func_type,
2441061da546Spatrick func_range); // first address range
2442061da546Spatrick
2443061da546Spatrick if (func_sp.get() != nullptr) {
2444061da546Spatrick if (frame_base.IsValid())
2445061da546Spatrick func_sp->GetFrameBaseExpression() = frame_base;
2446061da546Spatrick comp_unit.AddFunction(func_sp);
2447061da546Spatrick return func_sp.get();
2448061da546Spatrick }
2449061da546Spatrick }
2450061da546Spatrick return nullptr;
2451061da546Spatrick }
2452061da546Spatrick
2453*f6aab3d8Srobert namespace {
2454*f6aab3d8Srobert /// Parsed form of all attributes that are relevant for parsing type members.
2455*f6aab3d8Srobert struct MemberAttributes {
2456*f6aab3d8Srobert explicit MemberAttributes(const DWARFDIE &die, const DWARFDIE &parent_die,
2457*f6aab3d8Srobert ModuleSP module_sp);
2458061da546Spatrick const char *name = nullptr;
2459*f6aab3d8Srobert /// Indicates how many bits into the word (according to the host endianness)
2460*f6aab3d8Srobert /// the low-order bit of the field starts. Can be negative.
2461*f6aab3d8Srobert int64_t bit_offset = 0;
2462*f6aab3d8Srobert /// Indicates the size of the field in bits.
2463*f6aab3d8Srobert size_t bit_size = 0;
2464*f6aab3d8Srobert uint64_t data_bit_offset = UINT64_MAX;
2465*f6aab3d8Srobert AccessType accessibility = eAccessNone;
2466*f6aab3d8Srobert std::optional<uint64_t> byte_size;
2467*f6aab3d8Srobert std::optional<DWARFFormValue> const_value_form;
2468*f6aab3d8Srobert DWARFFormValue encoding_form;
2469*f6aab3d8Srobert /// Indicates the byte offset of the word from the base address of the
2470*f6aab3d8Srobert /// structure.
2471*f6aab3d8Srobert uint32_t member_byte_offset;
2472*f6aab3d8Srobert bool is_artificial = false;
2473*f6aab3d8Srobert };
2474*f6aab3d8Srobert
2475*f6aab3d8Srobert /// Parsed form of all attributes that are relevant for parsing Objective-C
2476*f6aab3d8Srobert /// properties.
2477*f6aab3d8Srobert struct PropertyAttributes {
2478*f6aab3d8Srobert explicit PropertyAttributes(const DWARFDIE &die);
2479061da546Spatrick const char *prop_name = nullptr;
2480061da546Spatrick const char *prop_getter_name = nullptr;
2481061da546Spatrick const char *prop_setter_name = nullptr;
2482*f6aab3d8Srobert /// \see clang::ObjCPropertyAttribute
2483061da546Spatrick uint32_t prop_attributes = 0;
2484*f6aab3d8Srobert };
2485*f6aab3d8Srobert } // namespace
2486061da546Spatrick
MemberAttributes(const DWARFDIE & die,const DWARFDIE & parent_die,ModuleSP module_sp)2487*f6aab3d8Srobert MemberAttributes::MemberAttributes(const DWARFDIE &die,
2488*f6aab3d8Srobert const DWARFDIE &parent_die,
2489*f6aab3d8Srobert ModuleSP module_sp) {
2490*f6aab3d8Srobert member_byte_offset = (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
2491*f6aab3d8Srobert
2492*f6aab3d8Srobert DWARFAttributes attributes;
2493*f6aab3d8Srobert const size_t num_attributes = die.GetAttributes(attributes);
2494*f6aab3d8Srobert for (std::size_t i = 0; i < num_attributes; ++i) {
2495061da546Spatrick const dw_attr_t attr = attributes.AttributeAtIndex(i);
2496061da546Spatrick DWARFFormValue form_value;
2497061da546Spatrick if (attributes.ExtractFormValueAtIndex(i, form_value)) {
2498061da546Spatrick switch (attr) {
2499061da546Spatrick case DW_AT_name:
2500061da546Spatrick name = form_value.AsCString();
2501061da546Spatrick break;
2502061da546Spatrick case DW_AT_type:
2503061da546Spatrick encoding_form = form_value;
2504061da546Spatrick break;
2505061da546Spatrick case DW_AT_bit_offset:
2506061da546Spatrick bit_offset = form_value.Signed();
2507061da546Spatrick break;
2508061da546Spatrick case DW_AT_bit_size:
2509061da546Spatrick bit_size = form_value.Unsigned();
2510061da546Spatrick break;
2511061da546Spatrick case DW_AT_byte_size:
2512061da546Spatrick byte_size = form_value.Unsigned();
2513061da546Spatrick break;
2514*f6aab3d8Srobert case DW_AT_const_value:
2515*f6aab3d8Srobert const_value_form = form_value;
2516*f6aab3d8Srobert break;
2517061da546Spatrick case DW_AT_data_bit_offset:
2518061da546Spatrick data_bit_offset = form_value.Unsigned();
2519061da546Spatrick break;
2520061da546Spatrick case DW_AT_data_member_location:
2521061da546Spatrick if (form_value.BlockData()) {
2522061da546Spatrick Value initialValue(0);
2523061da546Spatrick Value memberOffset(0);
2524061da546Spatrick const DWARFDataExtractor &debug_info_data = die.GetData();
2525061da546Spatrick uint32_t block_length = form_value.Unsigned();
2526061da546Spatrick uint32_t block_offset =
2527061da546Spatrick form_value.BlockData() - debug_info_data.GetDataStart();
2528061da546Spatrick if (DWARFExpression::Evaluate(
2529061da546Spatrick nullptr, // ExecutionContext *
2530061da546Spatrick nullptr, // RegisterContext *
2531061da546Spatrick module_sp,
2532061da546Spatrick DataExtractor(debug_info_data, block_offset, block_length),
2533061da546Spatrick die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
2534061da546Spatrick memberOffset, nullptr)) {
2535061da546Spatrick member_byte_offset = memberOffset.ResolveValue(nullptr).UInt();
2536061da546Spatrick }
2537061da546Spatrick } else {
2538061da546Spatrick // With DWARF 3 and later, if the value is an integer constant,
2539061da546Spatrick // this form value is the offset in bytes from the beginning of
2540061da546Spatrick // the containing entity.
2541061da546Spatrick member_byte_offset = form_value.Unsigned();
2542061da546Spatrick }
2543061da546Spatrick break;
2544061da546Spatrick
2545061da546Spatrick case DW_AT_accessibility:
2546*f6aab3d8Srobert accessibility = DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned());
2547061da546Spatrick break;
2548061da546Spatrick case DW_AT_artificial:
2549061da546Spatrick is_artificial = form_value.Boolean();
2550061da546Spatrick break;
2551061da546Spatrick default:
2552061da546Spatrick break;
2553061da546Spatrick }
2554061da546Spatrick }
2555061da546Spatrick }
2556061da546Spatrick
2557061da546Spatrick // Clang has a DWARF generation bug where sometimes it represents
2558061da546Spatrick // fields that are references with bad byte size and bit size/offset
2559061da546Spatrick // information such as:
2560061da546Spatrick //
2561061da546Spatrick // DW_AT_byte_size( 0x00 )
2562061da546Spatrick // DW_AT_bit_size( 0x40 )
2563061da546Spatrick // DW_AT_bit_offset( 0xffffffffffffffc0 )
2564061da546Spatrick //
2565061da546Spatrick // So check the bit offset to make sure it is sane, and if the values
2566061da546Spatrick // are not sane, remove them. If we don't do this then we will end up
2567061da546Spatrick // with a crash if we try to use this type in an expression when clang
2568061da546Spatrick // becomes unhappy with its recycled debug info.
2569*f6aab3d8Srobert if (byte_size.value_or(0) == 0 && bit_offset < 0) {
2570061da546Spatrick bit_size = 0;
2571061da546Spatrick bit_offset = 0;
2572061da546Spatrick }
2573*f6aab3d8Srobert }
2574*f6aab3d8Srobert
PropertyAttributes(const DWARFDIE & die)2575*f6aab3d8Srobert PropertyAttributes::PropertyAttributes(const DWARFDIE &die) {
2576*f6aab3d8Srobert
2577*f6aab3d8Srobert DWARFAttributes attributes;
2578*f6aab3d8Srobert const size_t num_attributes = die.GetAttributes(attributes);
2579*f6aab3d8Srobert for (size_t i = 0; i < num_attributes; ++i) {
2580*f6aab3d8Srobert const dw_attr_t attr = attributes.AttributeAtIndex(i);
2581*f6aab3d8Srobert DWARFFormValue form_value;
2582*f6aab3d8Srobert if (attributes.ExtractFormValueAtIndex(i, form_value)) {
2583*f6aab3d8Srobert switch (attr) {
2584*f6aab3d8Srobert case DW_AT_APPLE_property_name:
2585*f6aab3d8Srobert prop_name = form_value.AsCString();
2586*f6aab3d8Srobert break;
2587*f6aab3d8Srobert case DW_AT_APPLE_property_getter:
2588*f6aab3d8Srobert prop_getter_name = form_value.AsCString();
2589*f6aab3d8Srobert break;
2590*f6aab3d8Srobert case DW_AT_APPLE_property_setter:
2591*f6aab3d8Srobert prop_setter_name = form_value.AsCString();
2592*f6aab3d8Srobert break;
2593*f6aab3d8Srobert case DW_AT_APPLE_property_attribute:
2594*f6aab3d8Srobert prop_attributes = form_value.Unsigned();
2595*f6aab3d8Srobert break;
2596*f6aab3d8Srobert default:
2597*f6aab3d8Srobert break;
2598*f6aab3d8Srobert }
2599*f6aab3d8Srobert }
2600*f6aab3d8Srobert }
2601*f6aab3d8Srobert
2602*f6aab3d8Srobert if (!prop_name)
2603*f6aab3d8Srobert return;
2604*f6aab3d8Srobert ConstString fixed_setter;
2605*f6aab3d8Srobert
2606*f6aab3d8Srobert // Check if the property getter/setter were provided as full names.
2607*f6aab3d8Srobert // We want basenames, so we extract them.
2608*f6aab3d8Srobert if (prop_getter_name && prop_getter_name[0] == '-') {
2609*f6aab3d8Srobert ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
2610*f6aab3d8Srobert prop_getter_name = prop_getter_method.GetSelector().GetCString();
2611*f6aab3d8Srobert }
2612*f6aab3d8Srobert
2613*f6aab3d8Srobert if (prop_setter_name && prop_setter_name[0] == '-') {
2614*f6aab3d8Srobert ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
2615*f6aab3d8Srobert prop_setter_name = prop_setter_method.GetSelector().GetCString();
2616*f6aab3d8Srobert }
2617*f6aab3d8Srobert
2618*f6aab3d8Srobert // If the names haven't been provided, they need to be filled in.
2619*f6aab3d8Srobert if (!prop_getter_name)
2620*f6aab3d8Srobert prop_getter_name = prop_name;
2621*f6aab3d8Srobert if (!prop_setter_name && prop_name[0] &&
2622*f6aab3d8Srobert !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
2623*f6aab3d8Srobert StreamString ss;
2624*f6aab3d8Srobert
2625*f6aab3d8Srobert ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);
2626*f6aab3d8Srobert
2627*f6aab3d8Srobert fixed_setter.SetString(ss.GetString());
2628*f6aab3d8Srobert prop_setter_name = fixed_setter.GetCString();
2629*f6aab3d8Srobert }
2630*f6aab3d8Srobert }
2631*f6aab3d8Srobert
ParseObjCProperty(const DWARFDIE & die,const DWARFDIE & parent_die,const lldb_private::CompilerType & class_clang_type,DelayedPropertyList & delayed_properties)2632*f6aab3d8Srobert void DWARFASTParserClang::ParseObjCProperty(
2633*f6aab3d8Srobert const DWARFDIE &die, const DWARFDIE &parent_die,
2634*f6aab3d8Srobert const lldb_private::CompilerType &class_clang_type,
2635*f6aab3d8Srobert DelayedPropertyList &delayed_properties) {
2636*f6aab3d8Srobert // This function can only parse DW_TAG_APPLE_property.
2637*f6aab3d8Srobert assert(die.Tag() == DW_TAG_APPLE_property);
2638*f6aab3d8Srobert
2639*f6aab3d8Srobert ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
2640*f6aab3d8Srobert
2641*f6aab3d8Srobert const MemberAttributes attrs(die, parent_die, module_sp);
2642*f6aab3d8Srobert const PropertyAttributes propAttrs(die);
2643*f6aab3d8Srobert
2644*f6aab3d8Srobert if (!propAttrs.prop_name) {
2645*f6aab3d8Srobert module_sp->ReportError("{0:x8}: DW_TAG_APPLE_property has no name.",
2646*f6aab3d8Srobert die.GetID());
2647*f6aab3d8Srobert return;
2648*f6aab3d8Srobert }
2649*f6aab3d8Srobert
2650*f6aab3d8Srobert Type *member_type = die.ResolveTypeUID(attrs.encoding_form.Reference());
2651*f6aab3d8Srobert if (!member_type) {
2652*f6aab3d8Srobert module_sp->ReportError(
2653*f6aab3d8Srobert "{0:x8}: DW_TAG_APPLE_property '{1}' refers to type {2:x16}"
2654*f6aab3d8Srobert " which was unable to be parsed",
2655*f6aab3d8Srobert die.GetID(), propAttrs.prop_name,
2656*f6aab3d8Srobert attrs.encoding_form.Reference().GetOffset());
2657*f6aab3d8Srobert return;
2658*f6aab3d8Srobert }
2659*f6aab3d8Srobert
2660*f6aab3d8Srobert ClangASTMetadata metadata;
2661*f6aab3d8Srobert metadata.SetUserID(die.GetID());
2662*f6aab3d8Srobert delayed_properties.push_back(DelayedAddObjCClassProperty(
2663*f6aab3d8Srobert class_clang_type, propAttrs.prop_name,
2664*f6aab3d8Srobert member_type->GetLayoutCompilerType(), propAttrs.prop_setter_name,
2665*f6aab3d8Srobert propAttrs.prop_getter_name, propAttrs.prop_attributes, &metadata));
2666*f6aab3d8Srobert }
2667*f6aab3d8Srobert
ExtractIntFromFormValue(const CompilerType & int_type,const DWARFFormValue & form_value) const2668*f6aab3d8Srobert llvm::Expected<llvm::APInt> DWARFASTParserClang::ExtractIntFromFormValue(
2669*f6aab3d8Srobert const CompilerType &int_type, const DWARFFormValue &form_value) const {
2670*f6aab3d8Srobert clang::QualType qt = ClangUtil::GetQualType(int_type);
2671*f6aab3d8Srobert assert(qt->isIntegralOrEnumerationType());
2672*f6aab3d8Srobert auto ts_ptr = int_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
2673*f6aab3d8Srobert if (!ts_ptr)
2674*f6aab3d8Srobert return llvm::createStringError(llvm::inconvertibleErrorCode(),
2675*f6aab3d8Srobert "TypeSystem not clang");
2676*f6aab3d8Srobert TypeSystemClang &ts = *ts_ptr;
2677*f6aab3d8Srobert clang::ASTContext &ast = ts.getASTContext();
2678*f6aab3d8Srobert
2679*f6aab3d8Srobert const unsigned type_bits = ast.getIntWidth(qt);
2680*f6aab3d8Srobert const bool is_unsigned = qt->isUnsignedIntegerType();
2681*f6aab3d8Srobert
2682*f6aab3d8Srobert // The maximum int size supported at the moment by this function. Limited
2683*f6aab3d8Srobert // by the uint64_t return type of DWARFFormValue::Signed/Unsigned.
2684*f6aab3d8Srobert constexpr std::size_t max_bit_size = 64;
2685*f6aab3d8Srobert
2686*f6aab3d8Srobert // For values bigger than 64 bit (e.g. __int128_t values),
2687*f6aab3d8Srobert // DWARFFormValue's Signed/Unsigned functions will return wrong results so
2688*f6aab3d8Srobert // emit an error for now.
2689*f6aab3d8Srobert if (type_bits > max_bit_size) {
2690*f6aab3d8Srobert auto msg = llvm::formatv("Can only parse integers with up to {0} bits, but "
2691*f6aab3d8Srobert "given integer has {1} bits.",
2692*f6aab3d8Srobert max_bit_size, type_bits);
2693*f6aab3d8Srobert return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.str());
2694*f6aab3d8Srobert }
2695*f6aab3d8Srobert
2696*f6aab3d8Srobert // Construct an APInt with the maximum bit size and the given integer.
2697*f6aab3d8Srobert llvm::APInt result(max_bit_size, form_value.Unsigned(), !is_unsigned);
2698*f6aab3d8Srobert
2699*f6aab3d8Srobert // Calculate how many bits are required to represent the input value.
2700*f6aab3d8Srobert // For unsigned types, take the number of active bits in the APInt.
2701*f6aab3d8Srobert // For signed types, ask APInt how many bits are required to represent the
2702*f6aab3d8Srobert // signed integer.
2703*f6aab3d8Srobert const unsigned required_bits =
2704*f6aab3d8Srobert is_unsigned ? result.getActiveBits() : result.getMinSignedBits();
2705*f6aab3d8Srobert
2706*f6aab3d8Srobert // If the input value doesn't fit into the integer type, return an error.
2707*f6aab3d8Srobert if (required_bits > type_bits) {
2708*f6aab3d8Srobert std::string value_as_str = is_unsigned
2709*f6aab3d8Srobert ? std::to_string(form_value.Unsigned())
2710*f6aab3d8Srobert : std::to_string(form_value.Signed());
2711*f6aab3d8Srobert auto msg = llvm::formatv("Can't store {0} value {1} in integer with {2} "
2712*f6aab3d8Srobert "bits.",
2713*f6aab3d8Srobert (is_unsigned ? "unsigned" : "signed"),
2714*f6aab3d8Srobert value_as_str, type_bits);
2715*f6aab3d8Srobert return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.str());
2716*f6aab3d8Srobert }
2717*f6aab3d8Srobert
2718*f6aab3d8Srobert // Trim the result to the bit width our the int type.
2719*f6aab3d8Srobert if (result.getBitWidth() > type_bits)
2720*f6aab3d8Srobert result = result.trunc(type_bits);
2721*f6aab3d8Srobert return result;
2722*f6aab3d8Srobert }
2723*f6aab3d8Srobert
ParseSingleMember(const DWARFDIE & die,const DWARFDIE & parent_die,const lldb_private::CompilerType & class_clang_type,lldb::AccessType default_accessibility,lldb_private::ClangASTImporter::LayoutInfo & layout_info,FieldInfo & last_field_info)2724*f6aab3d8Srobert void DWARFASTParserClang::ParseSingleMember(
2725*f6aab3d8Srobert const DWARFDIE &die, const DWARFDIE &parent_die,
2726*f6aab3d8Srobert const lldb_private::CompilerType &class_clang_type,
2727*f6aab3d8Srobert lldb::AccessType default_accessibility,
2728*f6aab3d8Srobert lldb_private::ClangASTImporter::LayoutInfo &layout_info,
2729*f6aab3d8Srobert FieldInfo &last_field_info) {
2730*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
2731*f6aab3d8Srobert // This function can only parse DW_TAG_member.
2732*f6aab3d8Srobert assert(die.Tag() == DW_TAG_member);
2733*f6aab3d8Srobert
2734*f6aab3d8Srobert ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
2735*f6aab3d8Srobert const dw_tag_t tag = die.Tag();
2736*f6aab3d8Srobert // Get the parent byte size so we can verify any members will fit
2737*f6aab3d8Srobert const uint64_t parent_byte_size =
2738*f6aab3d8Srobert parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);
2739*f6aab3d8Srobert const uint64_t parent_bit_size =
2740*f6aab3d8Srobert parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8;
2741*f6aab3d8Srobert
2742*f6aab3d8Srobert // FIXME: Remove the workarounds below and make this const.
2743*f6aab3d8Srobert MemberAttributes attrs(die, parent_die, module_sp);
2744061da546Spatrick
2745dda28197Spatrick const bool class_is_objc_object_or_interface =
2746dda28197Spatrick TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type);
2747dda28197Spatrick
2748061da546Spatrick // FIXME: Make Clang ignore Objective-C accessibility for expressions
2749dda28197Spatrick if (class_is_objc_object_or_interface)
2750*f6aab3d8Srobert attrs.accessibility = eAccessNone;
2751061da546Spatrick
2752*f6aab3d8Srobert // Handle static members, which is any member that doesn't have a bit or a
2753*f6aab3d8Srobert // byte member offset.
2754*f6aab3d8Srobert if (attrs.member_byte_offset == UINT32_MAX &&
2755*f6aab3d8Srobert attrs.data_bit_offset == UINT64_MAX) {
2756*f6aab3d8Srobert Type *var_type = die.ResolveTypeUID(attrs.encoding_form.Reference());
2757061da546Spatrick
2758061da546Spatrick if (var_type) {
2759*f6aab3d8Srobert if (attrs.accessibility == eAccessNone)
2760*f6aab3d8Srobert attrs.accessibility = eAccessPublic;
2761*f6aab3d8Srobert CompilerType ct = var_type->GetForwardCompilerType();
2762*f6aab3d8Srobert clang::VarDecl *v = TypeSystemClang::AddVariableToRecordType(
2763*f6aab3d8Srobert class_clang_type, attrs.name, ct, attrs.accessibility);
2764*f6aab3d8Srobert if (!v) {
2765*f6aab3d8Srobert LLDB_LOG(log, "Failed to add variable to the record type");
2766*f6aab3d8Srobert return;
2767*f6aab3d8Srobert }
2768*f6aab3d8Srobert
2769*f6aab3d8Srobert bool unused;
2770*f6aab3d8Srobert // TODO: Support float/double static members as well.
2771*f6aab3d8Srobert if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused))
2772*f6aab3d8Srobert return;
2773*f6aab3d8Srobert
2774*f6aab3d8Srobert llvm::Expected<llvm::APInt> const_value_or_err =
2775*f6aab3d8Srobert ExtractIntFromFormValue(ct, *attrs.const_value_form);
2776*f6aab3d8Srobert if (!const_value_or_err) {
2777*f6aab3d8Srobert LLDB_LOG_ERROR(log, const_value_or_err.takeError(),
2778*f6aab3d8Srobert "Failed to add const value to variable {1}: {0}",
2779*f6aab3d8Srobert v->getQualifiedNameAsString());
2780*f6aab3d8Srobert return;
2781*f6aab3d8Srobert }
2782*f6aab3d8Srobert
2783*f6aab3d8Srobert TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err);
2784061da546Spatrick }
2785061da546Spatrick return;
2786061da546Spatrick }
2787061da546Spatrick
2788*f6aab3d8Srobert Type *member_type = die.ResolveTypeUID(attrs.encoding_form.Reference());
2789*f6aab3d8Srobert if (!member_type) {
2790*f6aab3d8Srobert if (attrs.name)
2791*f6aab3d8Srobert module_sp->ReportError(
2792*f6aab3d8Srobert "{0:x8}: DW_TAG_member '{1}' refers to type {2:x16}"
2793*f6aab3d8Srobert " which was unable to be parsed",
2794*f6aab3d8Srobert die.GetID(), attrs.name, attrs.encoding_form.Reference().GetOffset());
2795*f6aab3d8Srobert else
2796*f6aab3d8Srobert module_sp->ReportError("{0:x8}: DW_TAG_member refers to type {1:x16}"
2797*f6aab3d8Srobert " which was unable to be parsed",
2798*f6aab3d8Srobert die.GetID(),
2799*f6aab3d8Srobert attrs.encoding_form.Reference().GetOffset());
2800*f6aab3d8Srobert return;
2801*f6aab3d8Srobert }
2802061da546Spatrick
2803061da546Spatrick const uint64_t character_width = 8;
2804061da546Spatrick const uint64_t word_width = 32;
2805061da546Spatrick CompilerType member_clang_type = member_type->GetLayoutCompilerType();
2806061da546Spatrick
2807*f6aab3d8Srobert if (attrs.accessibility == eAccessNone)
2808*f6aab3d8Srobert attrs.accessibility = default_accessibility;
2809061da546Spatrick
2810*f6aab3d8Srobert uint64_t field_bit_offset = (attrs.member_byte_offset == UINT32_MAX
2811*f6aab3d8Srobert ? 0
2812*f6aab3d8Srobert : (attrs.member_byte_offset * 8ULL));
2813061da546Spatrick
2814*f6aab3d8Srobert if (attrs.bit_size > 0) {
2815061da546Spatrick FieldInfo this_field_info;
2816061da546Spatrick this_field_info.bit_offset = field_bit_offset;
2817*f6aab3d8Srobert this_field_info.bit_size = attrs.bit_size;
2818061da546Spatrick
2819*f6aab3d8Srobert if (attrs.data_bit_offset != UINT64_MAX) {
2820*f6aab3d8Srobert this_field_info.bit_offset = attrs.data_bit_offset;
2821061da546Spatrick } else {
2822*f6aab3d8Srobert if (!attrs.byte_size)
2823*f6aab3d8Srobert attrs.byte_size = member_type->GetByteSize(nullptr);
2824061da546Spatrick
2825061da546Spatrick ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
2826061da546Spatrick if (objfile->GetByteOrder() == eByteOrderLittle) {
2827*f6aab3d8Srobert this_field_info.bit_offset += attrs.byte_size.value_or(0) * 8;
2828*f6aab3d8Srobert this_field_info.bit_offset -= (attrs.bit_offset + attrs.bit_size);
2829061da546Spatrick } else {
2830*f6aab3d8Srobert this_field_info.bit_offset += attrs.bit_offset;
2831061da546Spatrick }
2832061da546Spatrick }
2833061da546Spatrick
2834be691f3bSpatrick // The ObjC runtime knows the byte offset but we still need to provide
2835be691f3bSpatrick // the bit-offset in the layout. It just means something different then
2836be691f3bSpatrick // what it does in C and C++. So we skip this check for ObjC types.
2837be691f3bSpatrick //
2838be691f3bSpatrick // We also skip this for fields of a union since they will all have a
2839be691f3bSpatrick // zero offset.
2840be691f3bSpatrick if (!TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type) &&
2841*f6aab3d8Srobert !(parent_die.Tag() == DW_TAG_union_type &&
2842*f6aab3d8Srobert this_field_info.bit_offset == 0) &&
2843be691f3bSpatrick ((this_field_info.bit_offset >= parent_bit_size) ||
2844061da546Spatrick (last_field_info.IsBitfield() &&
2845061da546Spatrick !last_field_info.NextBitfieldOffsetIsValid(
2846be691f3bSpatrick this_field_info.bit_offset)))) {
2847061da546Spatrick ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
2848061da546Spatrick objfile->GetModule()->ReportWarning(
2849*f6aab3d8Srobert "{0:x16}: {1} bitfield named \"{2}\" has invalid "
2850*f6aab3d8Srobert "bit offset ({3:x8}) member will be ignored. Please file a bug "
2851*f6aab3d8Srobert "against the "
2852*f6aab3d8Srobert "compiler and include the preprocessed output for {4}\n",
2853*f6aab3d8Srobert die.GetID(), DW_TAG_value_to_name(tag), attrs.name,
2854061da546Spatrick this_field_info.bit_offset, GetUnitName(parent_die).c_str());
2855061da546Spatrick return;
2856061da546Spatrick }
2857061da546Spatrick
2858061da546Spatrick // Update the field bit offset we will report for layout
2859061da546Spatrick field_bit_offset = this_field_info.bit_offset;
2860061da546Spatrick
2861061da546Spatrick // Objective-C has invalid DW_AT_bit_offset values in older
2862061da546Spatrick // versions of clang, so we have to be careful and only insert
2863061da546Spatrick // unnamed bitfields if we have a new enough clang.
2864061da546Spatrick bool detect_unnamed_bitfields = true;
2865061da546Spatrick
2866dda28197Spatrick if (class_is_objc_object_or_interface)
2867061da546Spatrick detect_unnamed_bitfields =
2868061da546Spatrick die.GetCU()->Supports_unnamed_objc_bitfields();
2869061da546Spatrick
2870061da546Spatrick if (detect_unnamed_bitfields) {
2871*f6aab3d8Srobert std::optional<FieldInfo> unnamed_field_info;
2872061da546Spatrick uint64_t last_field_end = 0;
2873061da546Spatrick
2874*f6aab3d8Srobert last_field_end = last_field_info.bit_offset + last_field_info.bit_size;
2875061da546Spatrick
2876061da546Spatrick if (!last_field_info.IsBitfield()) {
2877061da546Spatrick // The last field was not a bit-field...
2878061da546Spatrick // but if it did take up the entire word then we need to extend
2879061da546Spatrick // last_field_end so the bit-field does not step into the last
2880061da546Spatrick // fields padding.
2881061da546Spatrick if (last_field_end != 0 && ((last_field_end % word_width) != 0))
2882061da546Spatrick last_field_end += word_width - (last_field_end % word_width);
2883061da546Spatrick }
2884061da546Spatrick
2885061da546Spatrick // If we have a gap between the last_field_end and the current
2886dda28197Spatrick // field we have an unnamed bit-field.
2887dda28197Spatrick // If we have a base class, we assume there is no unnamed
2888dda28197Spatrick // bit-field if this is the first field since the gap can be
2889dda28197Spatrick // attributed to the members from the base class. This assumption
2890dda28197Spatrick // is not correct if the first field of the derived class is
2891dda28197Spatrick // indeed an unnamed bit-field. We currently do not have the
2892dda28197Spatrick // machinary to track the offset of the last field of classes we
2893dda28197Spatrick // have seen before, so we are not handling this case.
2894061da546Spatrick if (this_field_info.bit_offset != last_field_end &&
2895dda28197Spatrick this_field_info.bit_offset > last_field_end &&
2896dda28197Spatrick !(last_field_info.bit_offset == 0 &&
2897dda28197Spatrick last_field_info.bit_size == 0 &&
2898dda28197Spatrick layout_info.base_offsets.size() != 0)) {
2899061da546Spatrick unnamed_field_info = FieldInfo{};
2900061da546Spatrick unnamed_field_info->bit_size =
2901061da546Spatrick this_field_info.bit_offset - last_field_end;
2902061da546Spatrick unnamed_field_info->bit_offset = last_field_end;
2903061da546Spatrick }
2904061da546Spatrick
2905061da546Spatrick if (unnamed_field_info) {
2906061da546Spatrick clang::FieldDecl *unnamed_bitfield_decl =
2907dda28197Spatrick TypeSystemClang::AddFieldToRecordType(
2908061da546Spatrick class_clang_type, llvm::StringRef(),
2909061da546Spatrick m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
2910061da546Spatrick word_width),
2911*f6aab3d8Srobert attrs.accessibility, unnamed_field_info->bit_size);
2912061da546Spatrick
2913061da546Spatrick layout_info.field_offsets.insert(std::make_pair(
2914061da546Spatrick unnamed_bitfield_decl, unnamed_field_info->bit_offset));
2915061da546Spatrick }
2916061da546Spatrick }
2917061da546Spatrick
2918061da546Spatrick last_field_info = this_field_info;
2919061da546Spatrick last_field_info.SetIsBitfield(true);
2920061da546Spatrick } else {
2921061da546Spatrick last_field_info.bit_offset = field_bit_offset;
2922061da546Spatrick
2923*f6aab3d8Srobert if (std::optional<uint64_t> clang_type_size =
2924be691f3bSpatrick member_type->GetByteSize(nullptr)) {
2925061da546Spatrick last_field_info.bit_size = *clang_type_size * character_width;
2926061da546Spatrick }
2927061da546Spatrick
2928061da546Spatrick last_field_info.SetIsBitfield(false);
2929061da546Spatrick }
2930061da546Spatrick
2931*f6aab3d8Srobert // Don't turn artificial members such as vtable pointers into real FieldDecls
2932*f6aab3d8Srobert // in our AST. Clang will re-create those articial members and they would
2933*f6aab3d8Srobert // otherwise just overlap in the layout with the FieldDecls we add here.
2934*f6aab3d8Srobert // This needs to be done after updating FieldInfo which keeps track of where
2935*f6aab3d8Srobert // field start/end so we don't later try to fill the the space of this
2936*f6aab3d8Srobert // artificial member with (unnamed bitfield) padding.
2937*f6aab3d8Srobert // FIXME: This check should verify that this is indeed an artificial member
2938*f6aab3d8Srobert // we are supposed to ignore.
2939*f6aab3d8Srobert if (attrs.is_artificial)
2940*f6aab3d8Srobert return;
2941*f6aab3d8Srobert
2942061da546Spatrick if (!member_clang_type.IsCompleteType())
2943061da546Spatrick member_clang_type.GetCompleteType();
2944061da546Spatrick
2945061da546Spatrick {
2946061da546Spatrick // Older versions of clang emit array[0] and array[1] in the
2947061da546Spatrick // same way (<rdar://problem/12566646>). If the current field
2948061da546Spatrick // is at the end of the structure, then there is definitely no
2949061da546Spatrick // room for extra elements and we override the type to
2950061da546Spatrick // array[0].
2951061da546Spatrick
2952061da546Spatrick CompilerType member_array_element_type;
2953061da546Spatrick uint64_t member_array_size;
2954061da546Spatrick bool member_array_is_incomplete;
2955061da546Spatrick
2956061da546Spatrick if (member_clang_type.IsArrayType(&member_array_element_type,
2957061da546Spatrick &member_array_size,
2958061da546Spatrick &member_array_is_incomplete) &&
2959061da546Spatrick !member_array_is_incomplete) {
2960061da546Spatrick uint64_t parent_byte_size =
2961*f6aab3d8Srobert parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);
2962061da546Spatrick
2963*f6aab3d8Srobert if (attrs.member_byte_offset >= parent_byte_size) {
2964061da546Spatrick if (member_array_size != 1 &&
2965061da546Spatrick (member_array_size != 0 ||
2966*f6aab3d8Srobert attrs.member_byte_offset > parent_byte_size)) {
2967061da546Spatrick module_sp->ReportError(
2968*f6aab3d8Srobert "{0:x8}: DW_TAG_member '{1}' refers to type {2:x16}"
2969*f6aab3d8Srobert " which extends beyond the bounds of {3:x8}",
2970*f6aab3d8Srobert die.GetID(), attrs.name,
2971*f6aab3d8Srobert attrs.encoding_form.Reference().GetOffset(), parent_die.GetID());
2972061da546Spatrick }
2973061da546Spatrick
2974061da546Spatrick member_clang_type =
2975061da546Spatrick m_ast.CreateArrayType(member_array_element_type, 0, false);
2976061da546Spatrick }
2977061da546Spatrick }
2978061da546Spatrick }
2979061da546Spatrick
2980*f6aab3d8Srobert TypeSystemClang::RequireCompleteType(member_clang_type);
2981061da546Spatrick
2982*f6aab3d8Srobert clang::FieldDecl *field_decl = TypeSystemClang::AddFieldToRecordType(
2983*f6aab3d8Srobert class_clang_type, attrs.name, member_clang_type, attrs.accessibility,
2984*f6aab3d8Srobert attrs.bit_size);
2985061da546Spatrick
2986061da546Spatrick m_ast.SetMetadataAsUserID(field_decl, die.GetID());
2987061da546Spatrick
2988061da546Spatrick layout_info.field_offsets.insert(
2989061da546Spatrick std::make_pair(field_decl, field_bit_offset));
2990061da546Spatrick }
2991061da546Spatrick
ParseChildMembers(const DWARFDIE & parent_die,CompilerType & class_clang_type,std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> & base_classes,std::vector<DWARFDIE> & member_function_dies,DelayedPropertyList & delayed_properties,const AccessType default_accessibility,ClangASTImporter::LayoutInfo & layout_info)2992061da546Spatrick bool DWARFASTParserClang::ParseChildMembers(
2993061da546Spatrick const DWARFDIE &parent_die, CompilerType &class_clang_type,
2994061da546Spatrick std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
2995061da546Spatrick std::vector<DWARFDIE> &member_function_dies,
2996*f6aab3d8Srobert DelayedPropertyList &delayed_properties,
2997*f6aab3d8Srobert const AccessType default_accessibility,
2998be691f3bSpatrick ClangASTImporter::LayoutInfo &layout_info) {
2999061da546Spatrick if (!parent_die)
3000061da546Spatrick return false;
3001061da546Spatrick
3002061da546Spatrick FieldInfo last_field_info;
3003061da546Spatrick
3004061da546Spatrick ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
3005*f6aab3d8Srobert auto ts = class_clang_type.GetTypeSystem();
3006*f6aab3d8Srobert auto ast = ts.dyn_cast_or_null<TypeSystemClang>();
3007061da546Spatrick if (ast == nullptr)
3008061da546Spatrick return false;
3009061da546Spatrick
3010be691f3bSpatrick for (DWARFDIE die : parent_die.children()) {
3011061da546Spatrick dw_tag_t tag = die.Tag();
3012061da546Spatrick
3013061da546Spatrick switch (tag) {
3014061da546Spatrick case DW_TAG_APPLE_property:
3015*f6aab3d8Srobert ParseObjCProperty(die, parent_die, class_clang_type, delayed_properties);
3016*f6aab3d8Srobert break;
3017*f6aab3d8Srobert
3018*f6aab3d8Srobert case DW_TAG_member:
3019dda28197Spatrick ParseSingleMember(die, parent_die, class_clang_type,
3020*f6aab3d8Srobert default_accessibility, layout_info, last_field_info);
3021061da546Spatrick break;
3022061da546Spatrick
3023061da546Spatrick case DW_TAG_subprogram:
3024061da546Spatrick // Let the type parsing code handle this one for us.
3025061da546Spatrick member_function_dies.push_back(die);
3026061da546Spatrick break;
3027061da546Spatrick
3028*f6aab3d8Srobert case DW_TAG_inheritance:
3029*f6aab3d8Srobert ParseInheritance(die, parent_die, class_clang_type, default_accessibility,
3030*f6aab3d8Srobert module_sp, base_classes, layout_info);
3031061da546Spatrick break;
3032061da546Spatrick
3033061da546Spatrick default:
3034061da546Spatrick break;
3035061da546Spatrick }
3036061da546Spatrick }
3037061da546Spatrick
3038061da546Spatrick return true;
3039061da546Spatrick }
3040061da546Spatrick
ParseChildParameters(clang::DeclContext * containing_decl_ctx,const DWARFDIE & parent_die,bool skip_artificial,bool & is_static,bool & is_variadic,bool & has_template_params,std::vector<CompilerType> & function_param_types,std::vector<clang::ParmVarDecl * > & function_param_decls,unsigned & type_quals)3041061da546Spatrick size_t DWARFASTParserClang::ParseChildParameters(
3042061da546Spatrick clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die,
3043061da546Spatrick bool skip_artificial, bool &is_static, bool &is_variadic,
3044061da546Spatrick bool &has_template_params, std::vector<CompilerType> &function_param_types,
3045061da546Spatrick std::vector<clang::ParmVarDecl *> &function_param_decls,
3046061da546Spatrick unsigned &type_quals) {
3047061da546Spatrick if (!parent_die)
3048061da546Spatrick return 0;
3049061da546Spatrick
3050061da546Spatrick size_t arg_idx = 0;
3051be691f3bSpatrick for (DWARFDIE die : parent_die.children()) {
3052061da546Spatrick const dw_tag_t tag = die.Tag();
3053061da546Spatrick switch (tag) {
3054061da546Spatrick case DW_TAG_formal_parameter: {
3055061da546Spatrick DWARFAttributes attributes;
3056061da546Spatrick const size_t num_attributes = die.GetAttributes(attributes);
3057061da546Spatrick if (num_attributes > 0) {
3058061da546Spatrick const char *name = nullptr;
3059061da546Spatrick DWARFFormValue param_type_die_form;
3060061da546Spatrick bool is_artificial = false;
3061061da546Spatrick // one of None, Auto, Register, Extern, Static, PrivateExtern
3062061da546Spatrick
3063061da546Spatrick clang::StorageClass storage = clang::SC_None;
3064061da546Spatrick uint32_t i;
3065061da546Spatrick for (i = 0; i < num_attributes; ++i) {
3066061da546Spatrick const dw_attr_t attr = attributes.AttributeAtIndex(i);
3067061da546Spatrick DWARFFormValue form_value;
3068061da546Spatrick if (attributes.ExtractFormValueAtIndex(i, form_value)) {
3069061da546Spatrick switch (attr) {
3070061da546Spatrick case DW_AT_name:
3071061da546Spatrick name = form_value.AsCString();
3072061da546Spatrick break;
3073061da546Spatrick case DW_AT_type:
3074061da546Spatrick param_type_die_form = form_value;
3075061da546Spatrick break;
3076061da546Spatrick case DW_AT_artificial:
3077061da546Spatrick is_artificial = form_value.Boolean();
3078061da546Spatrick break;
3079061da546Spatrick case DW_AT_location:
3080061da546Spatrick case DW_AT_const_value:
3081061da546Spatrick case DW_AT_default_value:
3082061da546Spatrick case DW_AT_description:
3083061da546Spatrick case DW_AT_endianity:
3084061da546Spatrick case DW_AT_is_optional:
3085061da546Spatrick case DW_AT_segment:
3086061da546Spatrick case DW_AT_variable_parameter:
3087061da546Spatrick default:
3088061da546Spatrick case DW_AT_abstract_origin:
3089061da546Spatrick case DW_AT_sibling:
3090061da546Spatrick break;
3091061da546Spatrick }
3092061da546Spatrick }
3093061da546Spatrick }
3094061da546Spatrick
3095061da546Spatrick bool skip = false;
3096061da546Spatrick if (skip_artificial && is_artificial) {
3097061da546Spatrick // In order to determine if a C++ member function is "const" we
3098061da546Spatrick // have to look at the const-ness of "this"...
3099061da546Spatrick if (arg_idx == 0 &&
3100061da546Spatrick DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()) &&
3101061da546Spatrick // Often times compilers omit the "this" name for the
3102061da546Spatrick // specification DIEs, so we can't rely upon the name being in
3103061da546Spatrick // the formal parameter DIE...
3104061da546Spatrick (name == nullptr || ::strcmp(name, "this") == 0)) {
3105061da546Spatrick Type *this_type =
3106061da546Spatrick die.ResolveTypeUID(param_type_die_form.Reference());
3107061da546Spatrick if (this_type) {
3108061da546Spatrick uint32_t encoding_mask = this_type->GetEncodingMask();
3109061da546Spatrick if (encoding_mask & Type::eEncodingIsPointerUID) {
3110061da546Spatrick is_static = false;
3111061da546Spatrick
3112061da546Spatrick if (encoding_mask & (1u << Type::eEncodingIsConstUID))
3113061da546Spatrick type_quals |= clang::Qualifiers::Const;
3114061da546Spatrick if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
3115061da546Spatrick type_quals |= clang::Qualifiers::Volatile;
3116061da546Spatrick }
3117061da546Spatrick }
3118061da546Spatrick }
3119061da546Spatrick skip = true;
3120061da546Spatrick }
3121061da546Spatrick
3122061da546Spatrick if (!skip) {
3123061da546Spatrick Type *type = die.ResolveTypeUID(param_type_die_form.Reference());
3124061da546Spatrick if (type) {
3125061da546Spatrick function_param_types.push_back(type->GetForwardCompilerType());
3126061da546Spatrick
3127061da546Spatrick clang::ParmVarDecl *param_var_decl =
3128dda28197Spatrick m_ast.CreateParameterDeclaration(
3129dda28197Spatrick containing_decl_ctx, GetOwningClangModule(die), name,
3130dda28197Spatrick type->GetForwardCompilerType(), storage);
3131061da546Spatrick assert(param_var_decl);
3132061da546Spatrick function_param_decls.push_back(param_var_decl);
3133061da546Spatrick
3134061da546Spatrick m_ast.SetMetadataAsUserID(param_var_decl, die.GetID());
3135061da546Spatrick }
3136061da546Spatrick }
3137061da546Spatrick }
3138061da546Spatrick arg_idx++;
3139061da546Spatrick } break;
3140061da546Spatrick
3141061da546Spatrick case DW_TAG_unspecified_parameters:
3142061da546Spatrick is_variadic = true;
3143061da546Spatrick break;
3144061da546Spatrick
3145061da546Spatrick case DW_TAG_template_type_parameter:
3146061da546Spatrick case DW_TAG_template_value_parameter:
3147061da546Spatrick case DW_TAG_GNU_template_parameter_pack:
3148061da546Spatrick // The one caller of this was never using the template_param_infos, and
3149061da546Spatrick // the local variable was taking up a large amount of stack space in
3150061da546Spatrick // SymbolFileDWARF::ParseType() so this was removed. If we ever need the
3151061da546Spatrick // template params back, we can add them back.
3152061da546Spatrick // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
3153061da546Spatrick has_template_params = true;
3154061da546Spatrick break;
3155061da546Spatrick
3156061da546Spatrick default:
3157061da546Spatrick break;
3158061da546Spatrick }
3159061da546Spatrick }
3160061da546Spatrick return arg_idx;
3161061da546Spatrick }
3162061da546Spatrick
GetTypeForDIE(const DWARFDIE & die)3163061da546Spatrick Type *DWARFASTParserClang::GetTypeForDIE(const DWARFDIE &die) {
3164061da546Spatrick if (die) {
3165061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
3166061da546Spatrick DWARFAttributes attributes;
3167061da546Spatrick const size_t num_attributes = die.GetAttributes(attributes);
3168061da546Spatrick if (num_attributes > 0) {
3169061da546Spatrick DWARFFormValue type_die_form;
3170061da546Spatrick for (size_t i = 0; i < num_attributes; ++i) {
3171061da546Spatrick dw_attr_t attr = attributes.AttributeAtIndex(i);
3172061da546Spatrick DWARFFormValue form_value;
3173061da546Spatrick
3174061da546Spatrick if (attr == DW_AT_type &&
3175061da546Spatrick attributes.ExtractFormValueAtIndex(i, form_value))
3176061da546Spatrick return dwarf->ResolveTypeUID(form_value.Reference(), true);
3177061da546Spatrick }
3178061da546Spatrick }
3179061da546Spatrick }
3180061da546Spatrick
3181061da546Spatrick return nullptr;
3182061da546Spatrick }
3183061da546Spatrick
GetClangDeclForDIE(const DWARFDIE & die)3184061da546Spatrick clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) {
3185061da546Spatrick if (!die)
3186061da546Spatrick return nullptr;
3187061da546Spatrick
3188061da546Spatrick switch (die.Tag()) {
3189061da546Spatrick case DW_TAG_variable:
3190061da546Spatrick case DW_TAG_constant:
3191061da546Spatrick case DW_TAG_formal_parameter:
3192061da546Spatrick case DW_TAG_imported_declaration:
3193061da546Spatrick case DW_TAG_imported_module:
3194061da546Spatrick break;
3195061da546Spatrick default:
3196061da546Spatrick return nullptr;
3197061da546Spatrick }
3198061da546Spatrick
3199061da546Spatrick DIEToDeclMap::iterator cache_pos = m_die_to_decl.find(die.GetDIE());
3200061da546Spatrick if (cache_pos != m_die_to_decl.end())
3201061da546Spatrick return cache_pos->second;
3202061da546Spatrick
3203061da546Spatrick if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) {
3204061da546Spatrick clang::Decl *decl = GetClangDeclForDIE(spec_die);
3205061da546Spatrick m_die_to_decl[die.GetDIE()] = decl;
3206061da546Spatrick return decl;
3207061da546Spatrick }
3208061da546Spatrick
3209061da546Spatrick if (DWARFDIE abstract_origin_die =
3210061da546Spatrick die.GetReferencedDIE(DW_AT_abstract_origin)) {
3211061da546Spatrick clang::Decl *decl = GetClangDeclForDIE(abstract_origin_die);
3212061da546Spatrick m_die_to_decl[die.GetDIE()] = decl;
3213061da546Spatrick return decl;
3214061da546Spatrick }
3215061da546Spatrick
3216061da546Spatrick clang::Decl *decl = nullptr;
3217061da546Spatrick switch (die.Tag()) {
3218061da546Spatrick case DW_TAG_variable:
3219061da546Spatrick case DW_TAG_constant:
3220061da546Spatrick case DW_TAG_formal_parameter: {
3221061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
3222061da546Spatrick Type *type = GetTypeForDIE(die);
3223061da546Spatrick if (dwarf && type) {
3224061da546Spatrick const char *name = die.GetName();
3225061da546Spatrick clang::DeclContext *decl_context =
3226dda28197Spatrick TypeSystemClang::DeclContextGetAsDeclContext(
3227061da546Spatrick dwarf->GetDeclContextContainingUID(die.GetID()));
3228061da546Spatrick decl = m_ast.CreateVariableDeclaration(
3229dda28197Spatrick decl_context, GetOwningClangModule(die), name,
3230061da546Spatrick ClangUtil::GetQualType(type->GetForwardCompilerType()));
3231061da546Spatrick }
3232061da546Spatrick break;
3233061da546Spatrick }
3234061da546Spatrick case DW_TAG_imported_declaration: {
3235061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
3236061da546Spatrick DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import);
3237061da546Spatrick if (imported_uid) {
3238dda28197Spatrick CompilerDecl imported_decl = SymbolFileDWARF::GetDecl(imported_uid);
3239061da546Spatrick if (imported_decl) {
3240061da546Spatrick clang::DeclContext *decl_context =
3241dda28197Spatrick TypeSystemClang::DeclContextGetAsDeclContext(
3242061da546Spatrick dwarf->GetDeclContextContainingUID(die.GetID()));
3243061da546Spatrick if (clang::NamedDecl *clang_imported_decl =
3244061da546Spatrick llvm::dyn_cast<clang::NamedDecl>(
3245061da546Spatrick (clang::Decl *)imported_decl.GetOpaqueDecl()))
3246dda28197Spatrick decl = m_ast.CreateUsingDeclaration(
3247dda28197Spatrick decl_context, OptionalClangModuleID(), clang_imported_decl);
3248061da546Spatrick }
3249061da546Spatrick }
3250061da546Spatrick break;
3251061da546Spatrick }
3252061da546Spatrick case DW_TAG_imported_module: {
3253061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
3254061da546Spatrick DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import);
3255061da546Spatrick
3256061da546Spatrick if (imported_uid) {
3257dda28197Spatrick CompilerDeclContext imported_decl_ctx =
3258dda28197Spatrick SymbolFileDWARF::GetDeclContext(imported_uid);
3259061da546Spatrick if (imported_decl_ctx) {
3260061da546Spatrick clang::DeclContext *decl_context =
3261dda28197Spatrick TypeSystemClang::DeclContextGetAsDeclContext(
3262061da546Spatrick dwarf->GetDeclContextContainingUID(die.GetID()));
3263061da546Spatrick if (clang::NamespaceDecl *ns_decl =
3264dda28197Spatrick TypeSystemClang::DeclContextGetAsNamespaceDecl(
3265061da546Spatrick imported_decl_ctx))
3266dda28197Spatrick decl = m_ast.CreateUsingDirectiveDeclaration(
3267dda28197Spatrick decl_context, OptionalClangModuleID(), ns_decl);
3268061da546Spatrick }
3269061da546Spatrick }
3270061da546Spatrick break;
3271061da546Spatrick }
3272061da546Spatrick default:
3273061da546Spatrick break;
3274061da546Spatrick }
3275061da546Spatrick
3276061da546Spatrick m_die_to_decl[die.GetDIE()] = decl;
3277061da546Spatrick
3278061da546Spatrick return decl;
3279061da546Spatrick }
3280061da546Spatrick
3281061da546Spatrick clang::DeclContext *
GetClangDeclContextForDIE(const DWARFDIE & die)3282061da546Spatrick DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
3283061da546Spatrick if (die) {
3284061da546Spatrick clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE(die);
3285061da546Spatrick if (decl_ctx)
3286061da546Spatrick return decl_ctx;
3287061da546Spatrick
3288061da546Spatrick bool try_parsing_type = true;
3289061da546Spatrick switch (die.Tag()) {
3290061da546Spatrick case DW_TAG_compile_unit:
3291061da546Spatrick case DW_TAG_partial_unit:
3292061da546Spatrick decl_ctx = m_ast.GetTranslationUnitDecl();
3293061da546Spatrick try_parsing_type = false;
3294061da546Spatrick break;
3295061da546Spatrick
3296061da546Spatrick case DW_TAG_namespace:
3297061da546Spatrick decl_ctx = ResolveNamespaceDIE(die);
3298061da546Spatrick try_parsing_type = false;
3299061da546Spatrick break;
3300061da546Spatrick
3301061da546Spatrick case DW_TAG_lexical_block:
3302061da546Spatrick decl_ctx = GetDeclContextForBlock(die);
3303061da546Spatrick try_parsing_type = false;
3304061da546Spatrick break;
3305061da546Spatrick
3306061da546Spatrick default:
3307061da546Spatrick break;
3308061da546Spatrick }
3309061da546Spatrick
3310061da546Spatrick if (decl_ctx == nullptr && try_parsing_type) {
3311061da546Spatrick Type *type = die.GetDWARF()->ResolveType(die);
3312061da546Spatrick if (type)
3313061da546Spatrick decl_ctx = GetCachedClangDeclContextForDIE(die);
3314061da546Spatrick }
3315061da546Spatrick
3316061da546Spatrick if (decl_ctx) {
3317061da546Spatrick LinkDeclContextToDIE(decl_ctx, die);
3318061da546Spatrick return decl_ctx;
3319061da546Spatrick }
3320061da546Spatrick }
3321061da546Spatrick return nullptr;
3322061da546Spatrick }
3323061da546Spatrick
3324dda28197Spatrick OptionalClangModuleID
GetOwningClangModule(const DWARFDIE & die)3325dda28197Spatrick DWARFASTParserClang::GetOwningClangModule(const DWARFDIE &die) {
3326dda28197Spatrick if (!die.IsValid())
3327dda28197Spatrick return {};
3328dda28197Spatrick
3329dda28197Spatrick for (DWARFDIE parent = die.GetParent(); parent.IsValid();
3330dda28197Spatrick parent = parent.GetParent()) {
3331dda28197Spatrick const dw_tag_t tag = parent.Tag();
3332dda28197Spatrick if (tag == DW_TAG_module) {
3333dda28197Spatrick DWARFDIE module_die = parent;
3334dda28197Spatrick auto it = m_die_to_module.find(module_die.GetDIE());
3335dda28197Spatrick if (it != m_die_to_module.end())
3336dda28197Spatrick return it->second;
3337*f6aab3d8Srobert const char *name =
3338*f6aab3d8Srobert module_die.GetAttributeValueAsString(DW_AT_name, nullptr);
3339dda28197Spatrick if (!name)
3340dda28197Spatrick return {};
3341dda28197Spatrick
3342dda28197Spatrick OptionalClangModuleID id =
3343dda28197Spatrick m_ast.GetOrCreateClangModule(name, GetOwningClangModule(module_die));
3344dda28197Spatrick m_die_to_module.insert({module_die.GetDIE(), id});
3345dda28197Spatrick return id;
3346dda28197Spatrick }
3347dda28197Spatrick }
3348dda28197Spatrick return {};
3349dda28197Spatrick }
3350dda28197Spatrick
IsSubroutine(const DWARFDIE & die)3351061da546Spatrick static bool IsSubroutine(const DWARFDIE &die) {
3352061da546Spatrick switch (die.Tag()) {
3353061da546Spatrick case DW_TAG_subprogram:
3354061da546Spatrick case DW_TAG_inlined_subroutine:
3355061da546Spatrick return true;
3356061da546Spatrick default:
3357061da546Spatrick return false;
3358061da546Spatrick }
3359061da546Spatrick }
3360061da546Spatrick
GetContainingFunctionWithAbstractOrigin(const DWARFDIE & die)3361061da546Spatrick static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) {
3362061da546Spatrick for (DWARFDIE candidate = die; candidate; candidate = candidate.GetParent()) {
3363061da546Spatrick if (IsSubroutine(candidate)) {
3364061da546Spatrick if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
3365061da546Spatrick return candidate;
3366061da546Spatrick } else {
3367061da546Spatrick return DWARFDIE();
3368061da546Spatrick }
3369061da546Spatrick }
3370061da546Spatrick }
3371061da546Spatrick assert(0 && "Shouldn't call GetContainingFunctionWithAbstractOrigin on "
3372061da546Spatrick "something not in a function");
3373061da546Spatrick return DWARFDIE();
3374061da546Spatrick }
3375061da546Spatrick
FindAnyChildWithAbstractOrigin(const DWARFDIE & context)3376061da546Spatrick static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) {
3377be691f3bSpatrick for (DWARFDIE candidate : context.children()) {
3378061da546Spatrick if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
3379061da546Spatrick return candidate;
3380061da546Spatrick }
3381061da546Spatrick }
3382061da546Spatrick return DWARFDIE();
3383061da546Spatrick }
3384061da546Spatrick
FindFirstChildWithAbstractOrigin(const DWARFDIE & block,const DWARFDIE & function)3385061da546Spatrick static DWARFDIE FindFirstChildWithAbstractOrigin(const DWARFDIE &block,
3386061da546Spatrick const DWARFDIE &function) {
3387061da546Spatrick assert(IsSubroutine(function));
3388061da546Spatrick for (DWARFDIE context = block; context != function.GetParent();
3389061da546Spatrick context = context.GetParent()) {
3390061da546Spatrick assert(!IsSubroutine(context) || context == function);
3391061da546Spatrick if (DWARFDIE child = FindAnyChildWithAbstractOrigin(context)) {
3392061da546Spatrick return child;
3393061da546Spatrick }
3394061da546Spatrick }
3395061da546Spatrick return DWARFDIE();
3396061da546Spatrick }
3397061da546Spatrick
3398061da546Spatrick clang::DeclContext *
GetDeclContextForBlock(const DWARFDIE & die)3399061da546Spatrick DWARFASTParserClang::GetDeclContextForBlock(const DWARFDIE &die) {
3400061da546Spatrick assert(die.Tag() == DW_TAG_lexical_block);
3401061da546Spatrick DWARFDIE containing_function_with_abstract_origin =
3402061da546Spatrick GetContainingFunctionWithAbstractOrigin(die);
3403061da546Spatrick if (!containing_function_with_abstract_origin) {
3404061da546Spatrick return (clang::DeclContext *)ResolveBlockDIE(die);
3405061da546Spatrick }
3406061da546Spatrick DWARFDIE child = FindFirstChildWithAbstractOrigin(
3407061da546Spatrick die, containing_function_with_abstract_origin);
3408061da546Spatrick CompilerDeclContext decl_context =
3409061da546Spatrick GetDeclContextContainingUIDFromDWARF(child);
3410061da546Spatrick return (clang::DeclContext *)decl_context.GetOpaqueDeclContext();
3411061da546Spatrick }
3412061da546Spatrick
ResolveBlockDIE(const DWARFDIE & die)3413061da546Spatrick clang::BlockDecl *DWARFASTParserClang::ResolveBlockDIE(const DWARFDIE &die) {
3414061da546Spatrick if (die && die.Tag() == DW_TAG_lexical_block) {
3415061da546Spatrick clang::BlockDecl *decl =
3416061da546Spatrick llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]);
3417061da546Spatrick
3418061da546Spatrick if (!decl) {
3419061da546Spatrick DWARFDIE decl_context_die;
3420061da546Spatrick clang::DeclContext *decl_context =
3421061da546Spatrick GetClangDeclContextContainingDIE(die, &decl_context_die);
3422dda28197Spatrick decl =
3423dda28197Spatrick m_ast.CreateBlockDeclaration(decl_context, GetOwningClangModule(die));
3424061da546Spatrick
3425061da546Spatrick if (decl)
3426061da546Spatrick LinkDeclContextToDIE((clang::DeclContext *)decl, die);
3427061da546Spatrick }
3428061da546Spatrick
3429061da546Spatrick return decl;
3430061da546Spatrick }
3431061da546Spatrick return nullptr;
3432061da546Spatrick }
3433061da546Spatrick
3434061da546Spatrick clang::NamespaceDecl *
ResolveNamespaceDIE(const DWARFDIE & die)3435061da546Spatrick DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
3436061da546Spatrick if (die && die.Tag() == DW_TAG_namespace) {
3437061da546Spatrick // See if we already parsed this namespace DIE and associated it with a
3438061da546Spatrick // uniqued namespace declaration
3439061da546Spatrick clang::NamespaceDecl *namespace_decl =
3440061da546Spatrick static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die.GetDIE()]);
3441061da546Spatrick if (namespace_decl)
3442061da546Spatrick return namespace_decl;
3443061da546Spatrick else {
3444061da546Spatrick const char *namespace_name = die.GetName();
3445061da546Spatrick clang::DeclContext *containing_decl_ctx =
3446061da546Spatrick GetClangDeclContextContainingDIE(die, nullptr);
3447061da546Spatrick bool is_inline =
3448061da546Spatrick die.GetAttributeValueAsUnsigned(DW_AT_export_symbols, 0) != 0;
3449061da546Spatrick
3450061da546Spatrick namespace_decl = m_ast.GetUniqueNamespaceDeclaration(
3451dda28197Spatrick namespace_name, containing_decl_ctx, GetOwningClangModule(die),
3452dda28197Spatrick is_inline);
3453061da546Spatrick
3454061da546Spatrick if (namespace_decl)
3455061da546Spatrick LinkDeclContextToDIE((clang::DeclContext *)namespace_decl, die);
3456061da546Spatrick return namespace_decl;
3457061da546Spatrick }
3458061da546Spatrick }
3459061da546Spatrick return nullptr;
3460061da546Spatrick }
3461061da546Spatrick
GetClangDeclContextContainingDIE(const DWARFDIE & die,DWARFDIE * decl_ctx_die_copy)3462061da546Spatrick clang::DeclContext *DWARFASTParserClang::GetClangDeclContextContainingDIE(
3463061da546Spatrick const DWARFDIE &die, DWARFDIE *decl_ctx_die_copy) {
3464061da546Spatrick SymbolFileDWARF *dwarf = die.GetDWARF();
3465061da546Spatrick
3466061da546Spatrick DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE(die);
3467061da546Spatrick
3468061da546Spatrick if (decl_ctx_die_copy)
3469061da546Spatrick *decl_ctx_die_copy = decl_ctx_die;
3470061da546Spatrick
3471061da546Spatrick if (decl_ctx_die) {
3472061da546Spatrick clang::DeclContext *clang_decl_ctx =
3473061da546Spatrick GetClangDeclContextForDIE(decl_ctx_die);
3474061da546Spatrick if (clang_decl_ctx)
3475061da546Spatrick return clang_decl_ctx;
3476061da546Spatrick }
3477061da546Spatrick return m_ast.GetTranslationUnitDecl();
3478061da546Spatrick }
3479061da546Spatrick
3480061da546Spatrick clang::DeclContext *
GetCachedClangDeclContextForDIE(const DWARFDIE & die)3481061da546Spatrick DWARFASTParserClang::GetCachedClangDeclContextForDIE(const DWARFDIE &die) {
3482061da546Spatrick if (die) {
3483061da546Spatrick DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE());
3484061da546Spatrick if (pos != m_die_to_decl_ctx.end())
3485061da546Spatrick return pos->second;
3486061da546Spatrick }
3487061da546Spatrick return nullptr;
3488061da546Spatrick }
3489061da546Spatrick
LinkDeclContextToDIE(clang::DeclContext * decl_ctx,const DWARFDIE & die)3490061da546Spatrick void DWARFASTParserClang::LinkDeclContextToDIE(clang::DeclContext *decl_ctx,
3491061da546Spatrick const DWARFDIE &die) {
3492061da546Spatrick m_die_to_decl_ctx[die.GetDIE()] = decl_ctx;
3493061da546Spatrick // There can be many DIEs for a single decl context
3494061da546Spatrick // m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE());
3495061da546Spatrick m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die));
3496061da546Spatrick }
3497061da546Spatrick
CopyUniqueClassMethodTypes(const DWARFDIE & src_class_die,const DWARFDIE & dst_class_die,lldb_private::Type * class_type,std::vector<DWARFDIE> & failures)3498061da546Spatrick bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
3499061da546Spatrick const DWARFDIE &src_class_die, const DWARFDIE &dst_class_die,
3500061da546Spatrick lldb_private::Type *class_type, std::vector<DWARFDIE> &failures) {
3501061da546Spatrick if (!class_type || !src_class_die || !dst_class_die)
3502061da546Spatrick return false;
3503061da546Spatrick if (src_class_die.Tag() != dst_class_die.Tag())
3504061da546Spatrick return false;
3505061da546Spatrick
3506061da546Spatrick // We need to complete the class type so we can get all of the method types
3507061da546Spatrick // parsed so we can then unique those types to their equivalent counterparts
3508061da546Spatrick // in "dst_cu" and "dst_class_die"
3509061da546Spatrick class_type->GetFullCompilerType();
3510061da546Spatrick
3511*f6aab3d8Srobert auto gather = [](DWARFDIE die, UniqueCStringMap<DWARFDIE> &map,
3512*f6aab3d8Srobert UniqueCStringMap<DWARFDIE> &map_artificial) {
3513*f6aab3d8Srobert if (die.Tag() != DW_TAG_subprogram)
3514*f6aab3d8Srobert return;
3515*f6aab3d8Srobert // Make sure this is a declaration and not a concrete instance by looking
3516*f6aab3d8Srobert // for DW_AT_declaration set to 1. Sometimes concrete function instances are
3517*f6aab3d8Srobert // placed inside the class definitions and shouldn't be included in the list
3518*f6aab3d8Srobert // of things are are tracking here.
3519*f6aab3d8Srobert if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) != 1)
3520*f6aab3d8Srobert return;
3521*f6aab3d8Srobert
3522*f6aab3d8Srobert if (const char *name = die.GetMangledName()) {
3523*f6aab3d8Srobert ConstString const_name(name);
3524*f6aab3d8Srobert if (die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
3525*f6aab3d8Srobert map_artificial.Append(const_name, die);
3526*f6aab3d8Srobert else
3527*f6aab3d8Srobert map.Append(const_name, die);
3528*f6aab3d8Srobert }
3529*f6aab3d8Srobert };
3530*f6aab3d8Srobert
3531061da546Spatrick UniqueCStringMap<DWARFDIE> src_name_to_die;
3532061da546Spatrick UniqueCStringMap<DWARFDIE> dst_name_to_die;
3533061da546Spatrick UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;
3534061da546Spatrick UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial;
3535*f6aab3d8Srobert for (DWARFDIE src_die = src_class_die.GetFirstChild(); src_die.IsValid();
3536*f6aab3d8Srobert src_die = src_die.GetSibling()) {
3537*f6aab3d8Srobert gather(src_die, src_name_to_die, src_name_to_die_artificial);
3538061da546Spatrick }
3539*f6aab3d8Srobert for (DWARFDIE dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid();
3540*f6aab3d8Srobert dst_die = dst_die.GetSibling()) {
3541*f6aab3d8Srobert gather(dst_die, dst_name_to_die, dst_name_to_die_artificial);
3542061da546Spatrick }
3543061da546Spatrick const uint32_t src_size = src_name_to_die.GetSize();
3544061da546Spatrick const uint32_t dst_size = dst_name_to_die.GetSize();
3545061da546Spatrick
3546061da546Spatrick // Is everything kosher so we can go through the members at top speed?
3547061da546Spatrick bool fast_path = true;
3548061da546Spatrick
3549*f6aab3d8Srobert if (src_size != dst_size)
3550061da546Spatrick fast_path = false;
3551061da546Spatrick
3552061da546Spatrick uint32_t idx;
3553061da546Spatrick
3554061da546Spatrick if (fast_path) {
3555061da546Spatrick for (idx = 0; idx < src_size; ++idx) {
3556*f6aab3d8Srobert DWARFDIE src_die = src_name_to_die.GetValueAtIndexUnchecked(idx);
3557*f6aab3d8Srobert DWARFDIE dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
3558061da546Spatrick
3559*f6aab3d8Srobert if (src_die.Tag() != dst_die.Tag())
3560061da546Spatrick fast_path = false;
3561061da546Spatrick
3562061da546Spatrick const char *src_name = src_die.GetMangledName();
3563061da546Spatrick const char *dst_name = dst_die.GetMangledName();
3564061da546Spatrick
3565061da546Spatrick // Make sure the names match
3566061da546Spatrick if (src_name == dst_name || (strcmp(src_name, dst_name) == 0))
3567061da546Spatrick continue;
3568061da546Spatrick
3569061da546Spatrick fast_path = false;
3570061da546Spatrick }
3571061da546Spatrick }
3572061da546Spatrick
3573061da546Spatrick DWARFASTParserClang *src_dwarf_ast_parser =
3574dda28197Spatrick static_cast<DWARFASTParserClang *>(
3575*f6aab3d8Srobert SymbolFileDWARF::GetDWARFParser(*src_class_die.GetCU()));
3576061da546Spatrick DWARFASTParserClang *dst_dwarf_ast_parser =
3577dda28197Spatrick static_cast<DWARFASTParserClang *>(
3578*f6aab3d8Srobert SymbolFileDWARF::GetDWARFParser(*dst_class_die.GetCU()));
3579*f6aab3d8Srobert auto link = [&](DWARFDIE src, DWARFDIE dst) {
3580*f6aab3d8Srobert SymbolFileDWARF::DIEToTypePtr &die_to_type =
3581*f6aab3d8Srobert dst_class_die.GetDWARF()->GetDIEToType();
3582*f6aab3d8Srobert clang::DeclContext *dst_decl_ctx =
3583*f6aab3d8Srobert dst_dwarf_ast_parser->m_die_to_decl_ctx[dst.GetDIE()];
3584*f6aab3d8Srobert if (dst_decl_ctx)
3585*f6aab3d8Srobert src_dwarf_ast_parser->LinkDeclContextToDIE(dst_decl_ctx, src);
3586*f6aab3d8Srobert
3587*f6aab3d8Srobert if (Type *src_child_type = die_to_type[src.GetDIE()])
3588*f6aab3d8Srobert die_to_type[dst.GetDIE()] = src_child_type;
3589*f6aab3d8Srobert };
3590061da546Spatrick
3591061da546Spatrick // Now do the work of linking the DeclContexts and Types.
3592061da546Spatrick if (fast_path) {
3593061da546Spatrick // We can do this quickly. Just run across the tables index-for-index
3594061da546Spatrick // since we know each node has matching names and tags.
3595061da546Spatrick for (idx = 0; idx < src_size; ++idx) {
3596*f6aab3d8Srobert link(src_name_to_die.GetValueAtIndexUnchecked(idx),
3597*f6aab3d8Srobert dst_name_to_die.GetValueAtIndexUnchecked(idx));
3598061da546Spatrick }
3599061da546Spatrick } else {
3600061da546Spatrick // We must do this slowly. For each member of the destination, look up a
3601061da546Spatrick // member in the source with the same name, check its tag, and unique them
3602061da546Spatrick // if everything matches up. Report failures.
3603061da546Spatrick
3604061da546Spatrick if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) {
3605061da546Spatrick src_name_to_die.Sort();
3606061da546Spatrick
3607061da546Spatrick for (idx = 0; idx < dst_size; ++idx) {
3608061da546Spatrick ConstString dst_name = dst_name_to_die.GetCStringAtIndex(idx);
3609*f6aab3d8Srobert DWARFDIE dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
3610*f6aab3d8Srobert DWARFDIE src_die = src_name_to_die.Find(dst_name, DWARFDIE());
3611061da546Spatrick
3612*f6aab3d8Srobert if (src_die && (src_die.Tag() == dst_die.Tag()))
3613*f6aab3d8Srobert link(src_die, dst_die);
3614*f6aab3d8Srobert else
3615061da546Spatrick failures.push_back(dst_die);
3616061da546Spatrick }
3617061da546Spatrick }
3618061da546Spatrick }
3619061da546Spatrick
3620061da546Spatrick const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize();
3621061da546Spatrick const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize();
3622061da546Spatrick
3623061da546Spatrick if (src_size_artificial && dst_size_artificial) {
3624061da546Spatrick dst_name_to_die_artificial.Sort();
3625061da546Spatrick
3626061da546Spatrick for (idx = 0; idx < src_size_artificial; ++idx) {
3627061da546Spatrick ConstString src_name_artificial =
3628061da546Spatrick src_name_to_die_artificial.GetCStringAtIndex(idx);
3629*f6aab3d8Srobert DWARFDIE src_die =
3630*f6aab3d8Srobert src_name_to_die_artificial.GetValueAtIndexUnchecked(idx);
3631*f6aab3d8Srobert DWARFDIE dst_die =
3632061da546Spatrick dst_name_to_die_artificial.Find(src_name_artificial, DWARFDIE());
3633061da546Spatrick
3634061da546Spatrick // Both classes have the artificial types, link them
3635*f6aab3d8Srobert if (dst_die)
3636*f6aab3d8Srobert link(src_die, dst_die);
3637061da546Spatrick }
3638061da546Spatrick }
3639061da546Spatrick
3640061da546Spatrick if (dst_size_artificial) {
3641061da546Spatrick for (idx = 0; idx < dst_size_artificial; ++idx) {
3642*f6aab3d8Srobert failures.push_back(
3643*f6aab3d8Srobert dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx));
3644061da546Spatrick }
3645061da546Spatrick }
3646061da546Spatrick
3647061da546Spatrick return !failures.empty();
3648061da546Spatrick }
3649