Path: blob/main/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
39645 views
//===-- DWARFASTParserClang.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <cstdlib>910#include "DWARFASTParser.h"11#include "DWARFASTParserClang.h"12#include "DWARFDebugInfo.h"13#include "DWARFDeclContext.h"14#include "DWARFDefines.h"15#include "SymbolFileDWARF.h"16#include "SymbolFileDWARFDebugMap.h"17#include "SymbolFileDWARFDwo.h"18#include "UniqueDWARFASTType.h"1920#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"21#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"22#include "Plugins/ExpressionParser/Clang/ClangUtil.h"23#include "Plugins/Language/ObjC/ObjCLanguage.h"24#include "lldb/Core/Module.h"25#include "lldb/Core/Value.h"26#include "lldb/Host/Host.h"27#include "lldb/Symbol/CompileUnit.h"28#include "lldb/Symbol/Function.h"29#include "lldb/Symbol/ObjectFile.h"30#include "lldb/Symbol/SymbolFile.h"31#include "lldb/Symbol/TypeList.h"32#include "lldb/Symbol/TypeMap.h"33#include "lldb/Symbol/VariableList.h"34#include "lldb/Target/Language.h"35#include "lldb/Utility/LLDBAssert.h"36#include "lldb/Utility/Log.h"37#include "lldb/Utility/StreamString.h"3839#include "clang/AST/CXXInheritance.h"40#include "clang/AST/DeclBase.h"41#include "clang/AST/DeclCXX.h"42#include "clang/AST/DeclObjC.h"43#include "clang/AST/DeclTemplate.h"44#include "clang/AST/Type.h"45#include "llvm/ADT/StringExtras.h"46#include "llvm/Demangle/Demangle.h"4748#include <map>49#include <memory>50#include <optional>51#include <vector>5253//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN5455#ifdef ENABLE_DEBUG_PRINTF56#include <cstdio>57#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)58#else59#define DEBUG_PRINTF(fmt, ...)60#endif6162using namespace lldb;63using namespace lldb_private;64using namespace lldb_private::dwarf;65using namespace lldb_private::plugin::dwarf;6667DWARFASTParserClang::DWARFASTParserClang(TypeSystemClang &ast)68: DWARFASTParser(Kind::DWARFASTParserClang), m_ast(ast),69m_die_to_decl_ctx(), m_decl_ctx_to_die() {}7071DWARFASTParserClang::~DWARFASTParserClang() = default;7273static bool DeclKindIsCXXClass(clang::Decl::Kind decl_kind) {74switch (decl_kind) {75case clang::Decl::CXXRecord:76case clang::Decl::ClassTemplateSpecialization:77return true;78default:79break;80}81return false;82}838485ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() {86if (!m_clang_ast_importer_up) {87m_clang_ast_importer_up = std::make_unique<ClangASTImporter>();88}89return *m_clang_ast_importer_up;90}9192/// Detect a forward declaration that is nested in a DW_TAG_module.93static bool IsClangModuleFwdDecl(const DWARFDIE &Die) {94if (!Die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))95return false;96auto Parent = Die.GetParent();97while (Parent.IsValid()) {98if (Parent.Tag() == DW_TAG_module)99return true;100Parent = Parent.GetParent();101}102return false;103}104105static DWARFDIE GetContainingClangModuleDIE(const DWARFDIE &die) {106if (die.IsValid()) {107DWARFDIE top_module_die;108// Now make sure this DIE is scoped in a DW_TAG_module tag and return true109// if so110for (DWARFDIE parent = die.GetParent(); parent.IsValid();111parent = parent.GetParent()) {112const dw_tag_t tag = parent.Tag();113if (tag == DW_TAG_module)114top_module_die = parent;115else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)116break;117}118119return top_module_die;120}121return DWARFDIE();122}123124static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {125if (die.IsValid()) {126DWARFDIE clang_module_die = GetContainingClangModuleDIE(die);127128if (clang_module_die) {129const char *module_name = clang_module_die.GetName();130if (module_name)131return die.GetDWARF()->GetExternalModule(132lldb_private::ConstString(module_name));133}134}135return lldb::ModuleSP();136}137138// Returns true if the given artificial field name should be ignored when139// parsing the DWARF.140static bool ShouldIgnoreArtificialField(llvm::StringRef FieldName) {141return FieldName.starts_with("_vptr$")142// gdb emit vtable pointer as "_vptr.classname"143|| FieldName.starts_with("_vptr.");144}145146/// Returns true for C++ constructs represented by clang::CXXRecordDecl147static bool TagIsRecordType(dw_tag_t tag) {148switch (tag) {149case DW_TAG_class_type:150case DW_TAG_structure_type:151case DW_TAG_union_type:152return true;153default:154return false;155}156}157158TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,159const DWARFDIE &die,160Log *log) {161ModuleSP clang_module_sp = GetContainingClangModule(die);162if (!clang_module_sp)163return TypeSP();164165// If this type comes from a Clang module, recursively look in the166// DWARF section of the .pcm file in the module cache. Clang167// generates DWO skeleton units as breadcrumbs to find them.168std::vector<lldb_private::CompilerContext> die_context = die.GetDeclContext();169TypeQuery query(die_context, TypeQueryOptions::e_module_search |170TypeQueryOptions::e_find_one);171TypeResults results;172173// The type in the Clang module must have the same language as the current CU.174query.AddLanguage(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()));175clang_module_sp->FindTypes(query, results);176TypeSP pcm_type_sp = results.GetTypeMap().FirstType();177if (!pcm_type_sp) {178// Since this type is defined in one of the Clang modules imported179// by this symbol file, search all of them. Instead of calling180// sym_file->FindTypes(), which would return this again, go straight181// to the imported modules.182auto &sym_file = die.GetCU()->GetSymbolFileDWARF();183184// Well-formed clang modules never form cycles; guard against corrupted185// ones by inserting the current file.186results.AlreadySearched(&sym_file);187sym_file.ForEachExternalModule(188*sc.comp_unit, results.GetSearchedSymbolFiles(), [&](Module &module) {189module.FindTypes(query, results);190pcm_type_sp = results.GetTypeMap().FirstType();191return (bool)pcm_type_sp;192});193}194195if (!pcm_type_sp)196return TypeSP();197198// We found a real definition for this type in the Clang module, so lets use199// it and cache the fact that we found a complete type for this die.200lldb_private::CompilerType pcm_type = pcm_type_sp->GetForwardCompilerType();201lldb_private::CompilerType type =202GetClangASTImporter().CopyType(m_ast, pcm_type);203204if (!type)205return TypeSP();206207// Under normal operation pcm_type is a shallow forward declaration208// that gets completed later. This is necessary to support cyclic209// data structures. If, however, pcm_type is already complete (for210// example, because it was loaded for a different target before),211// the definition needs to be imported right away, too.212// Type::ResolveClangType() effectively ignores the ResolveState213// inside type_sp and only looks at IsDefined(), so it never calls214// ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(),215// which does extra work for Objective-C classes. This would result216// in only the forward declaration to be visible.217if (pcm_type.IsDefined())218GetClangASTImporter().RequireCompleteType(ClangUtil::GetQualType(type));219220SymbolFileDWARF *dwarf = die.GetDWARF();221auto type_sp = dwarf->MakeType(222die.GetID(), pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(nullptr),223nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid,224&pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward,225TypePayloadClang(GetOwningClangModule(die)));226clang::TagDecl *tag_decl = TypeSystemClang::GetAsTagDecl(type);227if (tag_decl) {228LinkDeclContextToDIE(tag_decl, die);229} else {230clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);231if (defn_decl_ctx)232LinkDeclContextToDIE(defn_decl_ctx, die);233}234235return type_sp;236}237238/// This function ensures we are able to add members (nested types, functions,239/// etc.) to this type. It does so by starting its definition even if one cannot240/// be found in the debug info. This means the type may need to be "forcibly241/// completed" later -- see CompleteTypeFromDWARF).242static void PrepareContextToReceiveMembers(TypeSystemClang &ast,243ClangASTImporter &ast_importer,244clang::DeclContext *decl_ctx,245DWARFDIE die,246const char *type_name_cstr) {247auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);248if (!tag_decl_ctx)249return; // Non-tag context are always ready.250251// We have already completed the type or it is already prepared.252if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())253return;254255// If this tag was imported from another AST context (in the gmodules case),256// we can complete the type by doing a full import.257258// If this type was not imported from an external AST, there's nothing to do.259CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);260if (type && ast_importer.CanImport(type)) {261auto qual_type = ClangUtil::GetQualType(type);262if (ast_importer.RequireCompleteType(qual_type))263return;264die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(265"Unable to complete the Decl context for DIE {0} at offset "266"{1:x16}.\nPlease file a bug report.",267type_name_cstr ? type_name_cstr : "", die.GetOffset());268}269270// We don't have a type definition and/or the import failed, but we need to271// add members to it. Start the definition to make that possible. If the type272// has no external storage we also have to complete the definition. Otherwise,273// that will happen when we are asked to complete the type274// (CompleteTypeFromDWARF).275ast.StartTagDeclarationDefinition(type);276if (!tag_decl_ctx->hasExternalLexicalStorage()) {277ast.SetDeclIsForcefullyCompleted(tag_decl_ctx);278ast.CompleteTagDeclarationDefinition(type);279}280}281282ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {283DWARFAttributes attributes = die.GetAttributes();284for (size_t i = 0; i < attributes.Size(); ++i) {285dw_attr_t attr = attributes.AttributeAtIndex(i);286DWARFFormValue form_value;287if (!attributes.ExtractFormValueAtIndex(i, form_value))288continue;289switch (attr) {290default:291break;292case DW_AT_abstract_origin:293abstract_origin = form_value;294break;295296case DW_AT_accessibility:297accessibility =298DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned());299break;300301case DW_AT_artificial:302is_artificial = form_value.Boolean();303break;304305case DW_AT_bit_stride:306bit_stride = form_value.Unsigned();307break;308309case DW_AT_byte_size:310byte_size = form_value.Unsigned();311break;312313case DW_AT_alignment:314alignment = form_value.Unsigned();315break;316317case DW_AT_byte_stride:318byte_stride = form_value.Unsigned();319break;320321case DW_AT_calling_convention:322calling_convention = form_value.Unsigned();323break;324325case DW_AT_containing_type:326containing_type = form_value;327break;328329case DW_AT_decl_file:330// die.GetCU() can differ if DW_AT_specification uses DW_FORM_ref_addr.331decl.SetFile(332attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));333break;334case DW_AT_decl_line:335decl.SetLine(form_value.Unsigned());336break;337case DW_AT_decl_column:338decl.SetColumn(form_value.Unsigned());339break;340341case DW_AT_declaration:342is_forward_declaration = form_value.Boolean();343break;344345case DW_AT_encoding:346encoding = form_value.Unsigned();347break;348349case DW_AT_enum_class:350is_scoped_enum = form_value.Boolean();351break;352353case DW_AT_explicit:354is_explicit = form_value.Boolean();355break;356357case DW_AT_external:358if (form_value.Unsigned())359storage = clang::SC_Extern;360break;361362case DW_AT_inline:363is_inline = form_value.Boolean();364break;365366case DW_AT_linkage_name:367case DW_AT_MIPS_linkage_name:368mangled_name = form_value.AsCString();369break;370371case DW_AT_name:372name.SetCString(form_value.AsCString());373break;374375case DW_AT_object_pointer:376object_pointer = form_value.Reference();377break;378379case DW_AT_signature:380signature = form_value;381break;382383case DW_AT_specification:384specification = form_value;385break;386387case DW_AT_type:388type = form_value;389break;390391case DW_AT_virtuality:392is_virtual = form_value.Boolean();393break;394395case DW_AT_APPLE_objc_complete_type:396is_complete_objc_class = form_value.Signed();397break;398399case DW_AT_APPLE_objc_direct:400is_objc_direct_call = true;401break;402403case DW_AT_APPLE_runtime_class:404class_language = (LanguageType)form_value.Signed();405break;406407case DW_AT_GNU_vector:408is_vector = form_value.Boolean();409break;410case DW_AT_export_symbols:411exports_symbols = form_value.Boolean();412break;413case DW_AT_rvalue_reference:414ref_qual = clang::RQ_RValue;415break;416case DW_AT_reference:417ref_qual = clang::RQ_LValue;418break;419}420}421}422423static std::string GetUnitName(const DWARFDIE &die) {424if (DWARFUnit *unit = die.GetCU())425return unit->GetAbsolutePath().GetPath();426return "<missing DWARF unit path>";427}428429TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,430const DWARFDIE &die,431bool *type_is_new_ptr) {432if (type_is_new_ptr)433*type_is_new_ptr = false;434435if (!die)436return nullptr;437438Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);439440SymbolFileDWARF *dwarf = die.GetDWARF();441if (log) {442DWARFDIE context_die;443clang::DeclContext *context =444GetClangDeclContextContainingDIE(die, &context_die);445446dwarf->GetObjectFile()->GetModule()->LogMessage(447log,448"DWARFASTParserClang::ParseTypeFromDWARF "449"(die = {0:x16}, decl_ctx = {1:p} (die "450"{2:x16})) {3} ({4}) name = '{5}')",451die.GetOffset(), static_cast<void *>(context), context_die.GetOffset(),452DW_TAG_value_to_name(die.Tag()), die.Tag(), die.GetName());453}454455// Set a bit that lets us know that we are currently parsing this456if (auto [it, inserted] =457dwarf->GetDIEToType().try_emplace(die.GetDIE(), DIE_IS_BEING_PARSED);458!inserted) {459if (it->getSecond() == nullptr || it->getSecond() == DIE_IS_BEING_PARSED)460return nullptr;461return it->getSecond()->shared_from_this();462}463464ParsedDWARFTypeAttributes attrs(die);465466TypeSP type_sp;467if (DWARFDIE signature_die = attrs.signature.Reference()) {468type_sp = ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr);469if (type_sp) {470if (clang::DeclContext *decl_ctx =471GetCachedClangDeclContextForDIE(signature_die))472LinkDeclContextToDIE(decl_ctx, die);473}474} else {475if (type_is_new_ptr)476*type_is_new_ptr = true;477478const dw_tag_t tag = die.Tag();479480switch (tag) {481case DW_TAG_typedef:482case DW_TAG_base_type:483case DW_TAG_pointer_type:484case DW_TAG_reference_type:485case DW_TAG_rvalue_reference_type:486case DW_TAG_const_type:487case DW_TAG_restrict_type:488case DW_TAG_volatile_type:489case DW_TAG_LLVM_ptrauth_type:490case DW_TAG_atomic_type:491case DW_TAG_unspecified_type:492type_sp = ParseTypeModifier(sc, die, attrs);493break;494case DW_TAG_structure_type:495case DW_TAG_union_type:496case DW_TAG_class_type:497type_sp = ParseStructureLikeDIE(sc, die, attrs);498break;499case DW_TAG_enumeration_type:500type_sp = ParseEnum(sc, die, attrs);501break;502case DW_TAG_inlined_subroutine:503case DW_TAG_subprogram:504case DW_TAG_subroutine_type:505type_sp = ParseSubroutine(die, attrs);506break;507case DW_TAG_array_type:508type_sp = ParseArrayType(die, attrs);509break;510case DW_TAG_ptr_to_member_type:511type_sp = ParsePointerToMemberType(die, attrs);512break;513default:514dwarf->GetObjectFile()->GetModule()->ReportError(515"[{0:x16}]: unhandled type tag {1:x4} ({2}), "516"please file a bug and "517"attach the file at the start of this error message",518die.GetOffset(), tag, DW_TAG_value_to_name(tag));519break;520}521UpdateSymbolContextScopeForType(sc, die, type_sp);522}523if (type_sp) {524dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();525}526return type_sp;527}528529static std::optional<uint32_t>530ExtractDataMemberLocation(DWARFDIE const &die, DWARFFormValue const &form_value,531ModuleSP module_sp) {532Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);533534// With DWARF 3 and later, if the value is an integer constant,535// this form value is the offset in bytes from the beginning of536// the containing entity.537if (!form_value.BlockData())538return form_value.Unsigned();539540Value initialValue(0);541const DWARFDataExtractor &debug_info_data = die.GetData();542uint32_t block_length = form_value.Unsigned();543uint32_t block_offset =544form_value.BlockData() - debug_info_data.GetDataStart();545546llvm::Expected<Value> memberOffset = DWARFExpression::Evaluate(547/*ExecutionContext=*/nullptr,548/*RegisterContext=*/nullptr, module_sp,549DataExtractor(debug_info_data, block_offset, block_length), die.GetCU(),550eRegisterKindDWARF, &initialValue, nullptr);551if (!memberOffset) {552LLDB_LOG_ERROR(log, memberOffset.takeError(),553"ExtractDataMemberLocation failed: {0}");554return {};555}556557return memberOffset->ResolveValue(nullptr).UInt();558}559560static TypePayloadClang GetPtrAuthMofidierPayload(const DWARFDIE &die) {561auto getAttr = [&](llvm::dwarf::Attribute Attr, unsigned defaultValue = 0) {562return die.GetAttributeValueAsUnsigned(Attr, defaultValue);563};564const unsigned key = getAttr(DW_AT_LLVM_ptrauth_key);565const bool addr_disc = getAttr(DW_AT_LLVM_ptrauth_address_discriminated);566const unsigned extra = getAttr(DW_AT_LLVM_ptrauth_extra_discriminator);567const bool isapointer = getAttr(DW_AT_LLVM_ptrauth_isa_pointer);568const bool authenticates_null_values =569getAttr(DW_AT_LLVM_ptrauth_authenticates_null_values);570const unsigned authentication_mode_int = getAttr(571DW_AT_LLVM_ptrauth_authentication_mode,572static_cast<unsigned>(clang::PointerAuthenticationMode::SignAndAuth));573clang::PointerAuthenticationMode authentication_mode =574clang::PointerAuthenticationMode::SignAndAuth;575if (authentication_mode_int >=576static_cast<unsigned>(clang::PointerAuthenticationMode::None) &&577authentication_mode_int <=578static_cast<unsigned>(579clang::PointerAuthenticationMode::SignAndAuth)) {580authentication_mode =581static_cast<clang::PointerAuthenticationMode>(authentication_mode_int);582} else {583die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(584"[{0:x16}]: invalid pointer authentication mode method {1:x4}",585die.GetOffset(), authentication_mode_int);586}587auto ptr_auth = clang::PointerAuthQualifier::Create(588key, addr_disc, extra, authentication_mode, isapointer,589authenticates_null_values);590return TypePayloadClang(ptr_auth.getAsOpaqueValue());591}592593lldb::TypeSP594DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,595const DWARFDIE &die,596ParsedDWARFTypeAttributes &attrs) {597Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);598SymbolFileDWARF *dwarf = die.GetDWARF();599const dw_tag_t tag = die.Tag();600LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());601Type::ResolveState resolve_state = Type::ResolveState::Unresolved;602Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;603TypePayloadClang payload(GetOwningClangModule(die));604TypeSP type_sp;605CompilerType clang_type;606607if (tag == DW_TAG_typedef) {608// DeclContext will be populated when the clang type is materialized in609// Type::ResolveCompilerType.610PrepareContextToReceiveMembers(611m_ast, GetClangASTImporter(),612GetClangDeclContextContainingDIE(die, nullptr), die,613attrs.name.GetCString());614615if (attrs.type.IsValid()) {616// Try to parse a typedef from the (DWARF embedded in the) Clang617// module file first as modules can contain typedef'ed618// structures that have no names like:619//620// typedef struct { int a; } Foo;621//622// In this case we will have a structure with no name and a623// typedef named "Foo" that points to this unnamed624// structure. The name in the typedef is the only identifier for625// the struct, so always try to get typedefs from Clang modules626// if possible.627//628// The type_sp returned will be empty if the typedef doesn't629// exist in a module file, so it is cheap to call this function630// just to check.631//632// If we don't do this we end up creating a TypeSP that says633// this is a typedef to type 0x123 (the DW_AT_type value would634// be 0x123 in the DW_TAG_typedef), and this is the unnamed635// structure type. We will have a hard time tracking down an636// unnammed structure type in the module debug info, so we make637// sure we don't get into this situation by always resolving638// typedefs from the module.639const DWARFDIE encoding_die = attrs.type.Reference();640641// First make sure that the die that this is typedef'ed to _is_642// just a declaration (DW_AT_declaration == 1), not a full643// definition since template types can't be represented in644// modules since only concrete instances of templates are ever645// emitted and modules won't contain those646if (encoding_die &&647encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {648type_sp = ParseTypeFromClangModule(sc, die, log);649if (type_sp)650return type_sp;651}652}653}654655DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(),656DW_TAG_value_to_name(tag), type_name_cstr,657encoding_uid.Reference());658659switch (tag) {660default:661break;662663case DW_TAG_unspecified_type:664if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") {665resolve_state = Type::ResolveState::Full;666clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);667break;668}669// Fall through to base type below in case we can handle the type670// there...671[[fallthrough]];672673case DW_TAG_base_type:674resolve_state = Type::ResolveState::Full;675clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(676attrs.name.GetStringRef(), attrs.encoding,677attrs.byte_size.value_or(0) * 8);678break;679680case DW_TAG_pointer_type:681encoding_data_type = Type::eEncodingIsPointerUID;682break;683case DW_TAG_reference_type:684encoding_data_type = Type::eEncodingIsLValueReferenceUID;685break;686case DW_TAG_rvalue_reference_type:687encoding_data_type = Type::eEncodingIsRValueReferenceUID;688break;689case DW_TAG_typedef:690encoding_data_type = Type::eEncodingIsTypedefUID;691break;692case DW_TAG_const_type:693encoding_data_type = Type::eEncodingIsConstUID;694break;695case DW_TAG_restrict_type:696encoding_data_type = Type::eEncodingIsRestrictUID;697break;698case DW_TAG_volatile_type:699encoding_data_type = Type::eEncodingIsVolatileUID;700break;701case DW_TAG_LLVM_ptrauth_type:702encoding_data_type = Type::eEncodingIsLLVMPtrAuthUID;703payload = GetPtrAuthMofidierPayload(die);704break;705case DW_TAG_atomic_type:706encoding_data_type = Type::eEncodingIsAtomicUID;707break;708}709710if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID ||711encoding_data_type == Type::eEncodingIsTypedefUID)) {712if (tag == DW_TAG_pointer_type) {713DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);714715if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) {716// Blocks have a __FuncPtr inside them which is a pointer to a717// function of the proper type.718719for (DWARFDIE child_die : target_die.children()) {720if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),721"__FuncPtr")) {722DWARFDIE function_pointer_type =723child_die.GetReferencedDIE(DW_AT_type);724725if (function_pointer_type) {726DWARFDIE function_type =727function_pointer_type.GetReferencedDIE(DW_AT_type);728729bool function_type_is_new_pointer;730TypeSP lldb_function_type_sp = ParseTypeFromDWARF(731sc, function_type, &function_type_is_new_pointer);732733if (lldb_function_type_sp) {734clang_type = m_ast.CreateBlockPointerType(735lldb_function_type_sp->GetForwardCompilerType());736encoding_data_type = Type::eEncodingIsUID;737attrs.type.Clear();738resolve_state = Type::ResolveState::Full;739}740}741742break;743}744}745}746}747748if (cu_language == eLanguageTypeObjC ||749cu_language == eLanguageTypeObjC_plus_plus) {750if (attrs.name) {751if (attrs.name == "id") {752if (log)753dwarf->GetObjectFile()->GetModule()->LogMessage(754log,755"SymbolFileDWARF::ParseType (die = {0:x16}) {1} ({2}) '{3}' "756"is Objective-C 'id' built-in type.",757die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),758die.GetName());759clang_type = m_ast.GetBasicType(eBasicTypeObjCID);760encoding_data_type = Type::eEncodingIsUID;761attrs.type.Clear();762resolve_state = Type::ResolveState::Full;763} else if (attrs.name == "Class") {764if (log)765dwarf->GetObjectFile()->GetModule()->LogMessage(766log,767"SymbolFileDWARF::ParseType (die = {0:x16}) {1} ({2}) '{3}' "768"is Objective-C 'Class' built-in type.",769die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),770die.GetName());771clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);772encoding_data_type = Type::eEncodingIsUID;773attrs.type.Clear();774resolve_state = Type::ResolveState::Full;775} else if (attrs.name == "SEL") {776if (log)777dwarf->GetObjectFile()->GetModule()->LogMessage(778log,779"SymbolFileDWARF::ParseType (die = {0:x16}) {1} ({2}) '{3}' "780"is Objective-C 'selector' built-in type.",781die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),782die.GetName());783clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);784encoding_data_type = Type::eEncodingIsUID;785attrs.type.Clear();786resolve_state = Type::ResolveState::Full;787}788} else if (encoding_data_type == Type::eEncodingIsPointerUID &&789attrs.type.IsValid()) {790// Clang sometimes erroneously emits id as objc_object*. In that791// case we fix up the type to "id".792793const DWARFDIE encoding_die = attrs.type.Reference();794795if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {796llvm::StringRef struct_name = encoding_die.GetName();797if (struct_name == "objc_object") {798if (log)799dwarf->GetObjectFile()->GetModule()->LogMessage(800log,801"SymbolFileDWARF::ParseType (die = {0:x16}) {1} ({2}) '{3}' "802"is 'objc_object*', which we overrode to 'id'.",803die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),804die.GetName());805clang_type = m_ast.GetBasicType(eBasicTypeObjCID);806encoding_data_type = Type::eEncodingIsUID;807attrs.type.Clear();808resolve_state = Type::ResolveState::Full;809}810}811}812}813}814815return dwarf->MakeType(die.GetID(), attrs.name, attrs.byte_size, nullptr,816attrs.type.Reference().GetID(), encoding_data_type,817&attrs.decl, clang_type, resolve_state, payload);818}819820std::string821DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {822if (llvm::StringRef(die.GetName()).contains("<"))823return {};824825TypeSystemClang::TemplateParameterInfos template_param_infos;826if (ParseTemplateParameterInfos(die, template_param_infos))827return m_ast.PrintTemplateParams(template_param_infos);828829return {};830}831832void DWARFASTParserClang::MapDeclDIEToDefDIE(833const lldb_private::plugin::dwarf::DWARFDIE &decl_die,834const lldb_private::plugin::dwarf::DWARFDIE &def_die) {835LinkDeclContextToDIE(GetCachedClangDeclContextForDIE(decl_die), def_die);836SymbolFileDWARF *dwarf = def_die.GetDWARF();837ParsedDWARFTypeAttributes decl_attrs(decl_die);838ParsedDWARFTypeAttributes def_attrs(def_die);839ConstString unique_typename(decl_attrs.name);840Declaration decl_declaration(decl_attrs.decl);841GetUniqueTypeNameAndDeclaration(842decl_die, SymbolFileDWARF::GetLanguage(*decl_die.GetCU()),843unique_typename, decl_declaration);844if (UniqueDWARFASTType *unique_ast_entry_type =845dwarf->GetUniqueDWARFASTTypeMap().Find(846unique_typename, decl_die, decl_declaration,847decl_attrs.byte_size.value_or(0),848decl_attrs.is_forward_declaration)) {849unique_ast_entry_type->UpdateToDefDIE(def_die, def_attrs.decl,850def_attrs.byte_size.value_or(0));851} else if (Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups)) {852const dw_tag_t tag = decl_die.Tag();853LLDB_LOG(log,854"Failed to find {0:x16} {1} ({2}) type \"{3}\" in "855"UniqueDWARFASTTypeMap",856decl_die.GetID(), DW_TAG_value_to_name(tag), tag, unique_typename);857}858}859860TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,861const DWARFDIE &decl_die,862ParsedDWARFTypeAttributes &attrs) {863Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);864SymbolFileDWARF *dwarf = decl_die.GetDWARF();865const dw_tag_t tag = decl_die.Tag();866867DWARFDIE def_die;868if (attrs.is_forward_declaration) {869if (TypeSP type_sp = ParseTypeFromClangModule(sc, decl_die, log))870return type_sp;871872def_die = dwarf->FindDefinitionDIE(decl_die);873874if (!def_die) {875SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();876if (debug_map_symfile) {877// We weren't able to find a full declaration in this DWARF,878// see if we have a declaration anywhere else...879def_die = debug_map_symfile->FindDefinitionDIE(decl_die);880}881}882883if (log) {884dwarf->GetObjectFile()->GetModule()->LogMessage(885log,886"SymbolFileDWARF({0:p}) - {1:x16}}: {2} ({3}) type \"{4}\" is a "887"forward declaration, complete DIE is {5}",888static_cast<void *>(this), decl_die.GetID(), DW_TAG_value_to_name(tag),889tag, attrs.name.GetCString(),890def_die ? llvm::utohexstr(def_die.GetID()) : "not found");891}892}893if (def_die) {894if (auto [it, inserted] = dwarf->GetDIEToType().try_emplace(895def_die.GetDIE(), DIE_IS_BEING_PARSED);896!inserted) {897if (it->getSecond() == nullptr || it->getSecond() == DIE_IS_BEING_PARSED)898return nullptr;899return it->getSecond()->shared_from_this();900}901attrs = ParsedDWARFTypeAttributes(def_die);902} else {903// No definition found. Proceed with the declaration die. We can use it to904// create a forward-declared type.905def_die = decl_die;906}907908CompilerType enumerator_clang_type;909if (attrs.type.IsValid()) {910Type *enumerator_type =911dwarf->ResolveTypeUID(attrs.type.Reference(), true);912if (enumerator_type)913enumerator_clang_type = enumerator_type->GetFullCompilerType();914}915916if (!enumerator_clang_type) {917if (attrs.byte_size) {918enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(919"", DW_ATE_signed, *attrs.byte_size * 8);920} else {921enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt);922}923}924925CompilerType clang_type = m_ast.CreateEnumerationType(926attrs.name.GetStringRef(), GetClangDeclContextContainingDIE(def_die, nullptr),927GetOwningClangModule(def_die), attrs.decl, enumerator_clang_type,928attrs.is_scoped_enum);929TypeSP type_sp =930dwarf->MakeType(def_die.GetID(), attrs.name, attrs.byte_size, nullptr,931attrs.type.Reference().GetID(), Type::eEncodingIsUID,932&attrs.decl, clang_type, Type::ResolveState::Forward,933TypePayloadClang(GetOwningClangModule(def_die)));934935clang::DeclContext *type_decl_ctx =936TypeSystemClang::GetDeclContextForType(clang_type);937LinkDeclContextToDIE(type_decl_ctx, decl_die);938if (decl_die != def_die) {939LinkDeclContextToDIE(type_decl_ctx, def_die);940dwarf->GetDIEToType()[def_die.GetDIE()] = type_sp.get();941// Declaration DIE is inserted into the type map in ParseTypeFromDWARF942}943944945if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) {946if (def_die.HasChildren()) {947bool is_signed = false;948enumerator_clang_type.IsIntegerType(is_signed);949ParseChildEnumerators(clang_type, is_signed,950type_sp->GetByteSize(nullptr).value_or(0), def_die);951}952TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);953} else {954dwarf->GetObjectFile()->GetModule()->ReportError(955"DWARF DIE at {0:x16} named \"{1}\" was not able to start its "956"definition.\nPlease file a bug and attach the file at the "957"start of this error message",958def_die.GetOffset(), attrs.name.GetCString());959}960return type_sp;961}962963static clang::CallingConv964ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes &attrs) {965switch (attrs.calling_convention) {966case llvm::dwarf::DW_CC_normal:967return clang::CC_C;968case llvm::dwarf::DW_CC_BORLAND_stdcall:969return clang::CC_X86StdCall;970case llvm::dwarf::DW_CC_BORLAND_msfastcall:971return clang::CC_X86FastCall;972case llvm::dwarf::DW_CC_LLVM_vectorcall:973return clang::CC_X86VectorCall;974case llvm::dwarf::DW_CC_BORLAND_pascal:975return clang::CC_X86Pascal;976case llvm::dwarf::DW_CC_LLVM_Win64:977return clang::CC_Win64;978case llvm::dwarf::DW_CC_LLVM_X86_64SysV:979return clang::CC_X86_64SysV;980case llvm::dwarf::DW_CC_LLVM_X86RegCall:981return clang::CC_X86RegCall;982default:983break;984}985986Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);987LLDB_LOG(log, "Unsupported DW_AT_calling_convention value: {0}",988attrs.calling_convention);989// Use the default calling convention as a fallback.990return clang::CC_C;991}992993bool DWARFASTParserClang::ParseObjCMethod(994const ObjCLanguage::MethodName &objc_method, const DWARFDIE &die,995CompilerType clang_type, const ParsedDWARFTypeAttributes &attrs,996bool is_variadic) {997SymbolFileDWARF *dwarf = die.GetDWARF();998assert(dwarf);9991000const auto tag = die.Tag();1001ConstString class_name(objc_method.GetClassName());1002if (!class_name)1003return false;10041005TypeSP complete_objc_class_type_sp =1006dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(), class_name,1007false);10081009if (!complete_objc_class_type_sp)1010return false;10111012CompilerType type_clang_forward_type =1013complete_objc_class_type_sp->GetForwardCompilerType();10141015if (!type_clang_forward_type)1016return false;10171018if (!TypeSystemClang::IsObjCObjectOrInterfaceType(type_clang_forward_type))1019return false;10201021clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType(1022type_clang_forward_type, attrs.name.GetCString(), clang_type,1023attrs.is_artificial, is_variadic, attrs.is_objc_direct_call);10241025if (!objc_method_decl) {1026dwarf->GetObjectFile()->GetModule()->ReportError(1027"[{0:x16}]: invalid Objective-C method {1:x4} ({2}), "1028"please file a bug and attach the file at the start of "1029"this error message",1030die.GetOffset(), tag, DW_TAG_value_to_name(tag));1031return false;1032}10331034LinkDeclContextToDIE(objc_method_decl, die);1035m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID());10361037return true;1038}10391040std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod(1041const DWARFDIE &die, CompilerType clang_type,1042const ParsedDWARFTypeAttributes &attrs, const DWARFDIE &decl_ctx_die,1043bool is_static, bool &ignore_containing_context) {1044Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);1045SymbolFileDWARF *dwarf = die.GetDWARF();1046assert(dwarf);10471048Type *class_type = dwarf->ResolveType(decl_ctx_die);1049if (!class_type)1050return {};10511052if (class_type->GetID() != decl_ctx_die.GetID() ||1053IsClangModuleFwdDecl(decl_ctx_die)) {10541055// We uniqued the parent class of this function to another1056// class so we now need to associate all dies under1057// "decl_ctx_die" to DIEs in the DIE for "class_type"...1058if (DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID())) {1059std::vector<DWARFDIE> failures;10601061CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, class_type,1062failures);10631064// FIXME do something with these failures that's1065// smarter than just dropping them on the ground.1066// Unfortunately classes don't like having stuff added1067// to them after their definitions are complete...10681069Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());1070if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)1071return {true, type_ptr->shared_from_this()};1072}1073}10741075if (attrs.specification.IsValid()) {1076// We have a specification which we are going to base our1077// function prototype off of, so we need this type to be1078// completed so that the m_die_to_decl_ctx for the method in1079// the specification has a valid clang decl context.1080class_type->GetForwardCompilerType();1081// If we have a specification, then the function type should1082// have been made with the specification and not with this1083// die.1084DWARFDIE spec_die = attrs.specification.Reference();1085clang::DeclContext *spec_clang_decl_ctx =1086GetClangDeclContextForDIE(spec_die);1087if (spec_clang_decl_ctx)1088LinkDeclContextToDIE(spec_clang_decl_ctx, die);1089else1090dwarf->GetObjectFile()->GetModule()->ReportWarning(1091"{0:x8}: DW_AT_specification({1:x16}"1092") has no decl\n",1093die.GetID(), spec_die.GetOffset());10941095return {true, nullptr};1096}10971098if (attrs.abstract_origin.IsValid()) {1099// We have a specification which we are going to base our1100// function prototype off of, so we need this type to be1101// completed so that the m_die_to_decl_ctx for the method in1102// the abstract origin has a valid clang decl context.1103class_type->GetForwardCompilerType();11041105DWARFDIE abs_die = attrs.abstract_origin.Reference();1106clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE(abs_die);1107if (abs_clang_decl_ctx)1108LinkDeclContextToDIE(abs_clang_decl_ctx, die);1109else1110dwarf->GetObjectFile()->GetModule()->ReportWarning(1111"{0:x8}: DW_AT_abstract_origin({1:x16}"1112") has no decl\n",1113die.GetID(), abs_die.GetOffset());11141115return {true, nullptr};1116}11171118CompilerType class_opaque_type = class_type->GetForwardCompilerType();1119if (!TypeSystemClang::IsCXXClassType(class_opaque_type))1120return {};11211122PrepareContextToReceiveMembers(1123m_ast, GetClangASTImporter(),1124TypeSystemClang::GetDeclContextForType(class_opaque_type), die,1125attrs.name.GetCString());11261127// We have a C++ member function with no children (this pointer!) and clang1128// will get mad if we try and make a function that isn't well formed in the1129// DWARF, so we will just skip it...1130if (!is_static && !die.HasChildren())1131return {true, nullptr};11321133const bool is_attr_used = false;1134// Neither GCC 4.2 nor clang++ currently set a valid1135// accessibility in the DWARF for C++ methods...1136// Default to public for now...1137const auto accessibility =1138attrs.accessibility == eAccessNone ? eAccessPublic : attrs.accessibility;11391140clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType(1141class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(),1142attrs.mangled_name, clang_type, accessibility, attrs.is_virtual,1143is_static, attrs.is_inline, attrs.is_explicit, is_attr_used,1144attrs.is_artificial);11451146if (cxx_method_decl) {1147LinkDeclContextToDIE(cxx_method_decl, die);11481149ClangASTMetadata metadata;1150metadata.SetUserID(die.GetID());11511152char const *object_pointer_name =1153attrs.object_pointer ? attrs.object_pointer.GetName() : nullptr;1154if (object_pointer_name) {1155metadata.SetObjectPtrName(object_pointer_name);1156LLDB_LOGF(log, "Setting object pointer name: %s on method object %p.\n",1157object_pointer_name, static_cast<void *>(cxx_method_decl));1158}1159m_ast.SetMetadata(cxx_method_decl, metadata);1160} else {1161ignore_containing_context = true;1162}11631164// Artificial methods are always handled even when we1165// don't create a new declaration for them.1166const bool type_handled = cxx_method_decl != nullptr || attrs.is_artificial;11671168return {type_handled, nullptr};1169}11701171TypeSP1172DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,1173const ParsedDWARFTypeAttributes &attrs) {1174Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);11751176SymbolFileDWARF *dwarf = die.GetDWARF();1177const dw_tag_t tag = die.Tag();11781179bool is_variadic = false;1180bool is_static = false;1181bool has_template_params = false;11821183unsigned type_quals = 0;11841185DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),1186DW_TAG_value_to_name(tag), type_name_cstr);11871188CompilerType return_clang_type;1189Type *func_type = nullptr;11901191if (attrs.type.IsValid())1192func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);11931194if (func_type)1195return_clang_type = func_type->GetForwardCompilerType();1196else1197return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);11981199std::vector<CompilerType> function_param_types;1200std::vector<clang::ParmVarDecl *> function_param_decls;12011202// Parse the function children for the parameters12031204DWARFDIE decl_ctx_die;1205clang::DeclContext *containing_decl_ctx =1206GetClangDeclContextContainingDIE(die, &decl_ctx_die);1207const clang::Decl::Kind containing_decl_kind =1208containing_decl_ctx->getDeclKind();12091210bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);1211// Start off static. This will be set to false in1212// ParseChildParameters(...) if we find a "this" parameters as the1213// first parameter1214if (is_cxx_method) {1215is_static = true;1216}12171218if (die.HasChildren()) {1219bool skip_artificial = true;1220ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static,1221is_variadic, has_template_params,1222function_param_types, function_param_decls,1223type_quals);1224}12251226bool ignore_containing_context = false;1227// Check for templatized class member functions. If we had any1228// DW_TAG_template_type_parameter or DW_TAG_template_value_parameter1229// the DW_TAG_subprogram DIE, then we can't let this become a method in1230// a class. Why? Because templatized functions are only emitted if one1231// of the templatized methods is used in the current compile unit and1232// we will end up with classes that may or may not include these member1233// functions and this means one class won't match another class1234// definition and it affects our ability to use a class in the clang1235// expression parser. So for the greater good, we currently must not1236// allow any template member functions in a class definition.1237if (is_cxx_method && has_template_params) {1238ignore_containing_context = true;1239is_cxx_method = false;1240}12411242clang::CallingConv calling_convention =1243ConvertDWARFCallingConventionToClang(attrs);12441245// clang_type will get the function prototype clang type after this1246// call1247CompilerType clang_type =1248m_ast.CreateFunctionType(return_clang_type, function_param_types.data(),1249function_param_types.size(), is_variadic,1250type_quals, calling_convention, attrs.ref_qual);12511252if (attrs.name) {1253bool type_handled = false;1254if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {1255if (std::optional<const ObjCLanguage::MethodName> objc_method =1256ObjCLanguage::MethodName::Create(attrs.name.GetStringRef(),1257true)) {1258type_handled =1259ParseObjCMethod(*objc_method, die, clang_type, attrs, is_variadic);1260} else if (is_cxx_method) {1261auto [handled, type_sp] =1262ParseCXXMethod(die, clang_type, attrs, decl_ctx_die, is_static,1263ignore_containing_context);1264if (type_sp)1265return type_sp;12661267type_handled = handled;1268}1269}12701271if (!type_handled) {1272clang::FunctionDecl *function_decl = nullptr;1273clang::FunctionDecl *template_function_decl = nullptr;12741275if (attrs.abstract_origin.IsValid()) {1276DWARFDIE abs_die = attrs.abstract_origin.Reference();12771278if (dwarf->ResolveType(abs_die)) {1279function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(1280GetCachedClangDeclContextForDIE(abs_die));12811282if (function_decl) {1283LinkDeclContextToDIE(function_decl, die);1284}1285}1286}12871288if (!function_decl) {1289char *name_buf = nullptr;1290llvm::StringRef name = attrs.name.GetStringRef();12911292// We currently generate function templates with template parameters in1293// their name. In order to get closer to the AST that clang generates1294// we want to strip these from the name when creating the AST.1295if (attrs.mangled_name) {1296llvm::ItaniumPartialDemangler D;1297if (!D.partialDemangle(attrs.mangled_name)) {1298name_buf = D.getFunctionBaseName(nullptr, nullptr);1299name = name_buf;1300}1301}13021303// We just have a function that isn't part of a class1304function_decl = m_ast.CreateFunctionDeclaration(1305ignore_containing_context ? m_ast.GetTranslationUnitDecl()1306: containing_decl_ctx,1307GetOwningClangModule(die), name, clang_type, attrs.storage,1308attrs.is_inline);1309std::free(name_buf);13101311if (has_template_params) {1312TypeSystemClang::TemplateParameterInfos template_param_infos;1313ParseTemplateParameterInfos(die, template_param_infos);1314template_function_decl = m_ast.CreateFunctionDeclaration(1315ignore_containing_context ? m_ast.GetTranslationUnitDecl()1316: containing_decl_ctx,1317GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type,1318attrs.storage, attrs.is_inline);1319clang::FunctionTemplateDecl *func_template_decl =1320m_ast.CreateFunctionTemplateDecl(1321containing_decl_ctx, GetOwningClangModule(die),1322template_function_decl, template_param_infos);1323m_ast.CreateFunctionTemplateSpecializationInfo(1324template_function_decl, func_template_decl, template_param_infos);1325}13261327lldbassert(function_decl);13281329if (function_decl) {1330// Attach an asm(<mangled_name>) label to the FunctionDecl.1331// This ensures that clang::CodeGen emits function calls1332// using symbols that are mangled according to the DW_AT_linkage_name.1333// If we didn't do this, the external symbols wouldn't exactly1334// match the mangled name LLDB knows about and the IRExecutionUnit1335// would have to fall back to searching object files for1336// approximately matching function names. The motivating1337// example is generating calls to ABI-tagged template functions.1338// This is done separately for member functions in1339// AddMethodToCXXRecordType.1340if (attrs.mangled_name)1341function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(1342m_ast.getASTContext(), attrs.mangled_name, /*literal=*/false));13431344LinkDeclContextToDIE(function_decl, die);13451346if (!function_param_decls.empty()) {1347m_ast.SetFunctionParameters(function_decl, function_param_decls);1348if (template_function_decl)1349m_ast.SetFunctionParameters(template_function_decl,1350function_param_decls);1351}13521353ClangASTMetadata metadata;1354metadata.SetUserID(die.GetID());13551356char const *object_pointer_name =1357attrs.object_pointer ? attrs.object_pointer.GetName() : nullptr;1358if (object_pointer_name) {1359metadata.SetObjectPtrName(object_pointer_name);1360LLDB_LOGF(log,1361"Setting object pointer name: %s on function "1362"object %p.",1363object_pointer_name, static_cast<void *>(function_decl));1364}1365m_ast.SetMetadata(function_decl, metadata);1366}1367}1368}1369}1370return dwarf->MakeType(1371die.GetID(), attrs.name, std::nullopt, nullptr, LLDB_INVALID_UID,1372Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Full);1373}13741375TypeSP1376DWARFASTParserClang::ParseArrayType(const DWARFDIE &die,1377const ParsedDWARFTypeAttributes &attrs) {1378SymbolFileDWARF *dwarf = die.GetDWARF();13791380DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),1381DW_TAG_value_to_name(tag), type_name_cstr);13821383DWARFDIE type_die = attrs.type.Reference();1384Type *element_type = dwarf->ResolveTypeUID(type_die, true);13851386if (!element_type)1387return nullptr;13881389std::optional<SymbolFile::ArrayInfo> array_info = ParseChildArrayInfo(die);1390uint32_t byte_stride = attrs.byte_stride;1391uint32_t bit_stride = attrs.bit_stride;1392if (array_info) {1393byte_stride = array_info->byte_stride;1394bit_stride = array_info->bit_stride;1395}1396if (byte_stride == 0 && bit_stride == 0)1397byte_stride = element_type->GetByteSize(nullptr).value_or(0);1398CompilerType array_element_type = element_type->GetForwardCompilerType();1399TypeSystemClang::RequireCompleteType(array_element_type);14001401uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;1402CompilerType clang_type;1403if (array_info && array_info->element_orders.size() > 0) {1404uint64_t num_elements = 0;1405auto end = array_info->element_orders.rend();1406for (auto pos = array_info->element_orders.rbegin(); pos != end; ++pos) {1407num_elements = *pos;1408clang_type = m_ast.CreateArrayType(array_element_type, num_elements,1409attrs.is_vector);1410array_element_type = clang_type;1411array_element_bit_stride = num_elements1412? array_element_bit_stride * num_elements1413: array_element_bit_stride;1414}1415} else {1416clang_type =1417m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector);1418}1419ConstString empty_name;1420TypeSP type_sp =1421dwarf->MakeType(die.GetID(), empty_name, array_element_bit_stride / 8,1422nullptr, type_die.GetID(), Type::eEncodingIsUID,1423&attrs.decl, clang_type, Type::ResolveState::Full);1424type_sp->SetEncodingType(element_type);1425const clang::Type *type = ClangUtil::GetQualType(clang_type).getTypePtr();1426m_ast.SetMetadataAsUserID(type, die.GetID());1427return type_sp;1428}14291430TypeSP DWARFASTParserClang::ParsePointerToMemberType(1431const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs) {1432SymbolFileDWARF *dwarf = die.GetDWARF();1433Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);1434Type *class_type =1435dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);14361437// Check to make sure pointers are not NULL before attempting to1438// dereference them.1439if ((class_type == nullptr) || (pointee_type == nullptr))1440return nullptr;14411442CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();1443CompilerType class_clang_type = class_type->GetForwardCompilerType();14441445CompilerType clang_type = TypeSystemClang::CreateMemberPointerType(1446class_clang_type, pointee_clang_type);14471448if (std::optional<uint64_t> clang_type_size =1449clang_type.GetByteSize(nullptr)) {1450return dwarf->MakeType(die.GetID(), attrs.name, *clang_type_size, nullptr,1451LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr,1452clang_type, Type::ResolveState::Forward);1453}1454return nullptr;1455}14561457void DWARFASTParserClang::ParseInheritance(1458const DWARFDIE &die, const DWARFDIE &parent_die,1459const CompilerType class_clang_type, const AccessType default_accessibility,1460const lldb::ModuleSP &module_sp,1461std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,1462ClangASTImporter::LayoutInfo &layout_info) {1463auto ast =1464class_clang_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();1465if (ast == nullptr)1466return;14671468// TODO: implement DW_TAG_inheritance type parsing.1469DWARFAttributes attributes = die.GetAttributes();1470if (attributes.Size() == 0)1471return;14721473DWARFFormValue encoding_form;1474AccessType accessibility = default_accessibility;1475bool is_virtual = false;1476bool is_base_of_class = true;1477off_t member_byte_offset = 0;14781479for (uint32_t i = 0; i < attributes.Size(); ++i) {1480const dw_attr_t attr = attributes.AttributeAtIndex(i);1481DWARFFormValue form_value;1482if (attributes.ExtractFormValueAtIndex(i, form_value)) {1483switch (attr) {1484case DW_AT_type:1485encoding_form = form_value;1486break;1487case DW_AT_data_member_location:1488if (auto maybe_offset =1489ExtractDataMemberLocation(die, form_value, module_sp))1490member_byte_offset = *maybe_offset;1491break;14921493case DW_AT_accessibility:1494accessibility =1495DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned());1496break;14971498case DW_AT_virtuality:1499is_virtual = form_value.Boolean();1500break;15011502default:1503break;1504}1505}1506}15071508Type *base_class_type = die.ResolveTypeUID(encoding_form.Reference());1509if (base_class_type == nullptr) {1510module_sp->ReportError("{0:x16}: DW_TAG_inheritance failed to "1511"resolve the base class at {1:x16}"1512" from enclosing type {2:x16}. \nPlease file "1513"a bug and attach the file at the start of "1514"this error message",1515die.GetOffset(),1516encoding_form.Reference().GetOffset(),1517parent_die.GetOffset());1518return;1519}15201521CompilerType base_class_clang_type = base_class_type->GetFullCompilerType();1522assert(base_class_clang_type);1523if (TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type)) {1524ast->SetObjCSuperClass(class_clang_type, base_class_clang_type);1525return;1526}1527std::unique_ptr<clang::CXXBaseSpecifier> result =1528ast->CreateBaseClassSpecifier(base_class_clang_type.GetOpaqueQualType(),1529accessibility, is_virtual,1530is_base_of_class);1531if (!result)1532return;15331534base_classes.push_back(std::move(result));15351536if (is_virtual) {1537// Do not specify any offset for virtual inheritance. The DWARF1538// produced by clang doesn't give us a constant offset, but gives1539// us a DWARF expressions that requires an actual object in memory.1540// the DW_AT_data_member_location for a virtual base class looks1541// like:1542// DW_AT_data_member_location( DW_OP_dup, DW_OP_deref,1543// DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref,1544// DW_OP_plus )1545// Given this, there is really no valid response we can give to1546// clang for virtual base class offsets, and this should eventually1547// be removed from LayoutRecordType() in the external1548// AST source in clang.1549} else {1550layout_info.base_offsets.insert(std::make_pair(1551ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()),1552clang::CharUnits::fromQuantity(member_byte_offset)));1553}1554}15551556TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(1557const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) {1558if (!type_sp)1559return type_sp;15601561DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);1562dw_tag_t sc_parent_tag = sc_parent_die.Tag();15631564SymbolContextScope *symbol_context_scope = nullptr;1565if (sc_parent_tag == DW_TAG_compile_unit ||1566sc_parent_tag == DW_TAG_partial_unit) {1567symbol_context_scope = sc.comp_unit;1568} else if (sc.function != nullptr && sc_parent_die) {1569symbol_context_scope =1570sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());1571if (symbol_context_scope == nullptr)1572symbol_context_scope = sc.function;1573} else {1574symbol_context_scope = sc.module_sp.get();1575}15761577if (symbol_context_scope != nullptr)1578type_sp->SetSymbolContextScope(symbol_context_scope);1579return type_sp;1580}15811582void DWARFASTParserClang::GetUniqueTypeNameAndDeclaration(1583const lldb_private::plugin::dwarf::DWARFDIE &die,1584lldb::LanguageType language, lldb_private::ConstString &unique_typename,1585lldb_private::Declaration &decl_declaration) {1586// For C++, we rely solely upon the one definition rule that says1587// only one thing can exist at a given decl context. We ignore the1588// file and line that things are declared on.1589if (!die.IsValid() || !Language::LanguageIsCPlusPlus(language) ||1590unique_typename.IsEmpty())1591return;1592decl_declaration.Clear();1593std::string qualified_name;1594DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE();1595// TODO: change this to get the correct decl context parent....1596while (parent_decl_ctx_die) {1597// The name may not contain template parameters due to1598// -gsimple-template-names; we must reconstruct the full name from child1599// template parameter dies via GetDIEClassTemplateParams().1600const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();1601switch (parent_tag) {1602case DW_TAG_namespace: {1603if (const char *namespace_name = parent_decl_ctx_die.GetName()) {1604qualified_name.insert(0, "::");1605qualified_name.insert(0, namespace_name);1606} else {1607qualified_name.insert(0, "(anonymous namespace)::");1608}1609parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();1610break;1611}16121613case DW_TAG_class_type:1614case DW_TAG_structure_type:1615case DW_TAG_union_type: {1616if (const char *class_union_struct_name = parent_decl_ctx_die.GetName()) {1617qualified_name.insert(16180, GetDIEClassTemplateParams(parent_decl_ctx_die));1619qualified_name.insert(0, "::");1620qualified_name.insert(0, class_union_struct_name);1621}1622parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();1623break;1624}16251626default:1627parent_decl_ctx_die.Clear();1628break;1629}1630}16311632if (qualified_name.empty())1633qualified_name.append("::");16341635qualified_name.append(unique_typename.GetCString());1636qualified_name.append(GetDIEClassTemplateParams(die));16371638unique_typename = ConstString(qualified_name);1639}16401641TypeSP1642DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,1643const DWARFDIE &die,1644ParsedDWARFTypeAttributes &attrs) {1645CompilerType clang_type;1646const dw_tag_t tag = die.Tag();1647SymbolFileDWARF *dwarf = die.GetDWARF();1648LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());1649Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);16501651ConstString unique_typename(attrs.name);1652Declaration unique_decl(attrs.decl);1653uint64_t byte_size = attrs.byte_size.value_or(0);1654if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&1655!die.HasChildren() && cu_language == eLanguageTypeObjC) {1656// Work around an issue with clang at the moment where forward1657// declarations for objective C classes are emitted as:1658// DW_TAG_structure_type [2]1659// DW_AT_name( "ForwardObjcClass" )1660// DW_AT_byte_size( 0x00 )1661// DW_AT_decl_file( "..." )1662// DW_AT_decl_line( 1 )1663//1664// Note that there is no DW_AT_declaration and there are no children,1665// and the byte size is zero.1666attrs.is_forward_declaration = true;1667}16681669if (attrs.name) {1670GetUniqueTypeNameAndDeclaration(die, cu_language, unique_typename,1671unique_decl);1672if (UniqueDWARFASTType *unique_ast_entry_type =1673dwarf->GetUniqueDWARFASTTypeMap().Find(1674unique_typename, die, unique_decl, byte_size,1675attrs.is_forward_declaration)) {1676if (TypeSP type_sp = unique_ast_entry_type->m_type_sp) {1677dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();1678LinkDeclContextToDIE(1679GetCachedClangDeclContextForDIE(unique_ast_entry_type->m_die), die);1680// If the DIE being parsed in this function is a definition and the1681// entry in the map is a declaration, then we need to update the entry1682// to point to the definition DIE.1683if (!attrs.is_forward_declaration &&1684unique_ast_entry_type->m_is_forward_declaration) {1685unique_ast_entry_type->UpdateToDefDIE(die, unique_decl, byte_size);1686clang_type = type_sp->GetForwardCompilerType();16871688CompilerType compiler_type_no_qualifiers =1689ClangUtil::RemoveFastQualifiers(clang_type);1690dwarf->GetForwardDeclCompilerTypeToDIE().insert_or_assign(1691compiler_type_no_qualifiers.GetOpaqueQualType(),1692*die.GetDIERef());1693}1694return type_sp;1695}1696}1697}16981699DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),1700DW_TAG_value_to_name(tag), type_name_cstr);17011702int tag_decl_kind = -1;1703AccessType default_accessibility = eAccessNone;1704if (tag == DW_TAG_structure_type) {1705tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Struct);1706default_accessibility = eAccessPublic;1707} else if (tag == DW_TAG_union_type) {1708tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Union);1709default_accessibility = eAccessPublic;1710} else if (tag == DW_TAG_class_type) {1711tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Class);1712default_accessibility = eAccessPrivate;1713}17141715if ((attrs.class_language == eLanguageTypeObjC ||1716attrs.class_language == eLanguageTypeObjC_plus_plus) &&1717!attrs.is_complete_objc_class &&1718die.Supports_DW_AT_APPLE_objc_complete_type()) {1719// We have a valid eSymbolTypeObjCClass class symbol whose name1720// matches the current objective C class that we are trying to find1721// and this DIE isn't the complete definition (we checked1722// is_complete_objc_class above and know it is false), so the real1723// definition is in here somewhere1724TypeSP type_sp =1725dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);17261727if (!type_sp) {1728SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();1729if (debug_map_symfile) {1730// We weren't able to find a full declaration in this DWARF,1731// see if we have a declaration anywhere else...1732type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(1733die, attrs.name, true);1734}1735}17361737if (type_sp) {1738if (log) {1739dwarf->GetObjectFile()->GetModule()->LogMessage(1740log,1741"SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is an "1742"incomplete objc type, complete type is {5:x8}",1743static_cast<void *>(this), die.GetID(), DW_TAG_value_to_name(tag),1744tag, attrs.name.GetCString(), type_sp->GetID());1745}1746return type_sp;1747}1748}17491750if (attrs.is_forward_declaration) {1751// See if the type comes from a Clang module and if so, track down1752// that type.1753TypeSP type_sp = ParseTypeFromClangModule(sc, die, log);1754if (type_sp)1755return type_sp;1756}17571758assert(tag_decl_kind != -1);1759UNUSED_IF_ASSERT_DISABLED(tag_decl_kind);1760clang::DeclContext *containing_decl_ctx =1761GetClangDeclContextContainingDIE(die, nullptr);17621763PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(),1764containing_decl_ctx, die,1765attrs.name.GetCString());17661767if (attrs.accessibility == eAccessNone && containing_decl_ctx) {1768// Check the decl context that contains this class/struct/union. If1769// it is a class we must give it an accessibility.1770const clang::Decl::Kind containing_decl_kind =1771containing_decl_ctx->getDeclKind();1772if (DeclKindIsCXXClass(containing_decl_kind))1773attrs.accessibility = default_accessibility;1774}17751776ClangASTMetadata metadata;1777metadata.SetUserID(die.GetID());1778metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die));17791780TypeSystemClang::TemplateParameterInfos template_param_infos;1781if (ParseTemplateParameterInfos(die, template_param_infos)) {1782clang::ClassTemplateDecl *class_template_decl =1783m_ast.ParseClassTemplateDecl(1784containing_decl_ctx, GetOwningClangModule(die), attrs.accessibility,1785attrs.name.GetCString(), tag_decl_kind, template_param_infos);1786if (!class_template_decl) {1787if (log) {1788dwarf->GetObjectFile()->GetModule()->LogMessage(1789log,1790"SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" "1791"clang::ClassTemplateDecl failed to return a decl.",1792static_cast<void *>(this), die.GetID(), DW_TAG_value_to_name(tag),1793tag, attrs.name.GetCString());1794}1795return TypeSP();1796}17971798clang::ClassTemplateSpecializationDecl *class_specialization_decl =1799m_ast.CreateClassTemplateSpecializationDecl(1800containing_decl_ctx, GetOwningClangModule(die), class_template_decl,1801tag_decl_kind, template_param_infos);1802clang_type =1803m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);18041805m_ast.SetMetadata(class_template_decl, metadata);1806m_ast.SetMetadata(class_specialization_decl, metadata);1807}18081809if (!clang_type) {1810clang_type = m_ast.CreateRecordType(1811containing_decl_ctx, GetOwningClangModule(die), attrs.accessibility,1812attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata,1813attrs.exports_symbols);1814}18151816TypeSP type_sp = dwarf->MakeType(1817die.GetID(), attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID,1818Type::eEncodingIsUID, &attrs.decl, clang_type,1819Type::ResolveState::Forward,1820TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class));18211822// Store a forward declaration to this class type in case any1823// parameters in any class methods need it for the clang types for1824// function prototypes.1825clang::DeclContext *type_decl_ctx =1826TypeSystemClang::GetDeclContextForType(clang_type);1827LinkDeclContextToDIE(type_decl_ctx, die);18281829// UniqueDWARFASTType is large, so don't create a local variables on the1830// stack, put it on the heap. This function is often called recursively and1831// clang isn't good at sharing the stack space for variables in different1832// blocks.1833auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>();1834// Add our type to the unique type map so we don't end up creating many1835// copies of the same type over and over in the ASTContext for our1836// module1837unique_ast_entry_up->m_type_sp = type_sp;1838unique_ast_entry_up->m_die = die;1839unique_ast_entry_up->m_declaration = unique_decl;1840unique_ast_entry_up->m_byte_size = byte_size;1841unique_ast_entry_up->m_is_forward_declaration = attrs.is_forward_declaration;1842dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,1843*unique_ast_entry_up);18441845// Leave this as a forward declaration until we need to know the1846// details of the type. lldb_private::Type will automatically call1847// the SymbolFile virtual function1848// "SymbolFileDWARF::CompleteType(Type *)" When the definition1849// needs to be defined.1850bool inserted =1851dwarf->GetForwardDeclCompilerTypeToDIE()1852.try_emplace(1853ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),1854*die.GetDIERef())1855.second;1856assert(inserted && "Type already in the forward declaration map!");1857(void)inserted;1858m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);18591860// If we made a clang type, set the trivial abi if applicable: We only1861// do this for pass by value - which implies the Trivial ABI. There1862// isn't a way to assert that something that would normally be pass by1863// value is pass by reference, so we ignore that attribute if set.1864if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) {1865clang::CXXRecordDecl *record_decl =1866m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());1867if (record_decl && record_decl->getDefinition()) {1868record_decl->setHasTrivialSpecialMemberForCall();1869}1870}18711872if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) {1873clang::CXXRecordDecl *record_decl =1874m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());1875if (record_decl)1876record_decl->setArgPassingRestrictions(1877clang::RecordArgPassingKind::CannotPassInRegs);1878}1879return type_sp;1880}18811882// DWARF parsing functions18831884class DWARFASTParserClang::DelayedAddObjCClassProperty {1885public:1886DelayedAddObjCClassProperty(1887const CompilerType &class_opaque_type, const char *property_name,1888const CompilerType &property_opaque_type, // The property type is only1889// required if you don't have an1890// ivar decl1891const char *property_setter_name, const char *property_getter_name,1892uint32_t property_attributes, const ClangASTMetadata *metadata)1893: m_class_opaque_type(class_opaque_type), m_property_name(property_name),1894m_property_opaque_type(property_opaque_type),1895m_property_setter_name(property_setter_name),1896m_property_getter_name(property_getter_name),1897m_property_attributes(property_attributes) {1898if (metadata != nullptr) {1899m_metadata_up = std::make_unique<ClangASTMetadata>();1900*m_metadata_up = *metadata;1901}1902}19031904DelayedAddObjCClassProperty(const DelayedAddObjCClassProperty &rhs) {1905*this = rhs;1906}19071908DelayedAddObjCClassProperty &1909operator=(const DelayedAddObjCClassProperty &rhs) {1910m_class_opaque_type = rhs.m_class_opaque_type;1911m_property_name = rhs.m_property_name;1912m_property_opaque_type = rhs.m_property_opaque_type;1913m_property_setter_name = rhs.m_property_setter_name;1914m_property_getter_name = rhs.m_property_getter_name;1915m_property_attributes = rhs.m_property_attributes;19161917if (rhs.m_metadata_up) {1918m_metadata_up = std::make_unique<ClangASTMetadata>();1919*m_metadata_up = *rhs.m_metadata_up;1920}1921return *this;1922}19231924bool Finalize() {1925return TypeSystemClang::AddObjCClassProperty(1926m_class_opaque_type, m_property_name, m_property_opaque_type,1927/*ivar_decl=*/nullptr, m_property_setter_name, m_property_getter_name,1928m_property_attributes, m_metadata_up.get());1929}19301931private:1932CompilerType m_class_opaque_type;1933const char *m_property_name;1934CompilerType m_property_opaque_type;1935const char *m_property_setter_name;1936const char *m_property_getter_name;1937uint32_t m_property_attributes;1938std::unique_ptr<ClangASTMetadata> m_metadata_up;1939};19401941bool DWARFASTParserClang::ParseTemplateDIE(1942const DWARFDIE &die,1943TypeSystemClang::TemplateParameterInfos &template_param_infos) {1944const dw_tag_t tag = die.Tag();1945bool is_template_template_argument = false;19461947switch (tag) {1948case DW_TAG_GNU_template_parameter_pack: {1949template_param_infos.SetParameterPack(1950std::make_unique<TypeSystemClang::TemplateParameterInfos>());1951for (DWARFDIE child_die : die.children()) {1952if (!ParseTemplateDIE(child_die, template_param_infos.GetParameterPack()))1953return false;1954}1955if (const char *name = die.GetName()) {1956template_param_infos.SetPackName(name);1957}1958return true;1959}1960case DW_TAG_GNU_template_template_param:1961is_template_template_argument = true;1962[[fallthrough]];1963case DW_TAG_template_type_parameter:1964case DW_TAG_template_value_parameter: {1965DWARFAttributes attributes = die.GetAttributes();1966if (attributes.Size() == 0)1967return true;19681969const char *name = nullptr;1970const char *template_name = nullptr;1971CompilerType clang_type;1972uint64_t uval64 = 0;1973bool uval64_valid = false;1974bool is_default_template_arg = false;1975DWARFFormValue form_value;1976for (size_t i = 0; i < attributes.Size(); ++i) {1977const dw_attr_t attr = attributes.AttributeAtIndex(i);19781979switch (attr) {1980case DW_AT_name:1981if (attributes.ExtractFormValueAtIndex(i, form_value))1982name = form_value.AsCString();1983break;19841985case DW_AT_GNU_template_name:1986if (attributes.ExtractFormValueAtIndex(i, form_value))1987template_name = form_value.AsCString();1988break;19891990case DW_AT_type:1991if (attributes.ExtractFormValueAtIndex(i, form_value)) {1992Type *lldb_type = die.ResolveTypeUID(form_value.Reference());1993if (lldb_type)1994clang_type = lldb_type->GetForwardCompilerType();1995}1996break;19971998case DW_AT_const_value:1999if (attributes.ExtractFormValueAtIndex(i, form_value)) {2000uval64_valid = true;2001uval64 = form_value.Unsigned();2002}2003break;2004case DW_AT_default_value:2005if (attributes.ExtractFormValueAtIndex(i, form_value))2006is_default_template_arg = form_value.Boolean();2007break;2008default:2009break;2010}2011}20122013clang::ASTContext &ast = m_ast.getASTContext();2014if (!clang_type)2015clang_type = m_ast.GetBasicType(eBasicTypeVoid);20162017if (!is_template_template_argument) {2018bool is_signed = false;2019// Get the signed value for any integer or enumeration if available2020clang_type.IsIntegerOrEnumerationType(is_signed);20212022if (name && !name[0])2023name = nullptr;20242025if (tag == DW_TAG_template_value_parameter && uval64_valid) {2026std::optional<uint64_t> size = clang_type.GetBitSize(nullptr);2027if (!size)2028return false;2029llvm::APInt apint(*size, uval64, is_signed);2030template_param_infos.InsertArg(2031name, clang::TemplateArgument(ast, llvm::APSInt(apint, !is_signed),2032ClangUtil::GetQualType(clang_type),2033is_default_template_arg));2034} else {2035template_param_infos.InsertArg(2036name, clang::TemplateArgument(ClangUtil::GetQualType(clang_type),2037/*isNullPtr*/ false,2038is_default_template_arg));2039}2040} else {2041auto *tplt_type = m_ast.CreateTemplateTemplateParmDecl(template_name);2042template_param_infos.InsertArg(2043name, clang::TemplateArgument(clang::TemplateName(tplt_type),2044is_default_template_arg));2045}2046}2047return true;20482049default:2050break;2051}2052return false;2053}20542055bool DWARFASTParserClang::ParseTemplateParameterInfos(2056const DWARFDIE &parent_die,2057TypeSystemClang::TemplateParameterInfos &template_param_infos) {20582059if (!parent_die)2060return false;20612062for (DWARFDIE die : parent_die.children()) {2063const dw_tag_t tag = die.Tag();20642065switch (tag) {2066case DW_TAG_template_type_parameter:2067case DW_TAG_template_value_parameter:2068case DW_TAG_GNU_template_parameter_pack:2069case DW_TAG_GNU_template_template_param:2070ParseTemplateDIE(die, template_param_infos);2071break;20722073default:2074break;2075}2076}20772078return !template_param_infos.IsEmpty() ||2079template_param_infos.hasParameterPack();2080}20812082bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,2083lldb_private::Type *type,2084CompilerType &clang_type) {2085const dw_tag_t tag = die.Tag();2086SymbolFileDWARF *dwarf = die.GetDWARF();20872088ClangASTImporter::LayoutInfo layout_info;2089std::vector<DWARFDIE> contained_type_dies;20902091if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))2092return false; // No definition, cannot complete.20932094// Start the definition if the type is not being defined already. This can2095// happen (e.g.) when adding nested types to a class type -- see2096// PrepareContextToReceiveMembers.2097if (!clang_type.IsBeingDefined())2098TypeSystemClang::StartTagDeclarationDefinition(clang_type);20992100AccessType default_accessibility = eAccessNone;2101if (tag == DW_TAG_structure_type) {2102default_accessibility = eAccessPublic;2103} else if (tag == DW_TAG_union_type) {2104default_accessibility = eAccessPublic;2105} else if (tag == DW_TAG_class_type) {2106default_accessibility = eAccessPrivate;2107}21082109std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;2110// Parse members and base classes first2111std::vector<DWARFDIE> member_function_dies;21122113DelayedPropertyList delayed_properties;2114ParseChildMembers(die, clang_type, bases, member_function_dies,2115contained_type_dies, delayed_properties,2116default_accessibility, layout_info);21172118// Now parse any methods if there were any...2119for (const DWARFDIE &die : member_function_dies)2120dwarf->ResolveType(die);21212122if (TypeSystemClang::IsObjCObjectOrInterfaceType(clang_type)) {2123ConstString class_name(clang_type.GetTypeName());2124if (class_name) {2125dwarf->GetObjCMethods(class_name, [&](DWARFDIE method_die) {2126method_die.ResolveType();2127return true;2128});21292130for (DelayedAddObjCClassProperty &property : delayed_properties)2131property.Finalize();2132}2133}21342135if (!bases.empty()) {2136// Make sure all base classes refer to complete types and not forward2137// declarations. If we don't do this, clang will crash with an2138// assertion in the call to clang_type.TransferBaseClasses()2139for (const auto &base_class : bases) {2140clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo();2141if (type_source_info)2142TypeSystemClang::RequireCompleteType(2143m_ast.GetType(type_source_info->getType()));2144}21452146m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(), std::move(bases));2147}21482149m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());2150TypeSystemClang::BuildIndirectFields(clang_type);2151TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);21522153if (type)2154layout_info.bit_size = type->GetByteSize(nullptr).value_or(0) * 8;2155if (layout_info.bit_size == 0)2156layout_info.bit_size =2157die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;2158if (layout_info.alignment == 0)2159layout_info.alignment =2160die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_alignment, 0) * 8;21612162clang::CXXRecordDecl *record_decl =2163m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());2164if (record_decl)2165GetClangASTImporter().SetRecordLayout(record_decl, layout_info);21662167// Now parse all contained types inside of the class. We make forward2168// declarations to all classes, but we need the CXXRecordDecl to have decls2169// for all contained types because we don't get asked for them via the2170// external AST support.2171for (const DWARFDIE &die : contained_type_dies)2172dwarf->ResolveType(die);21732174return (bool)clang_type;2175}21762177bool DWARFASTParserClang::CompleteEnumType(const DWARFDIE &die,2178lldb_private::Type *type,2179CompilerType &clang_type) {2180if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) {2181if (die.HasChildren()) {2182bool is_signed = false;2183clang_type.IsIntegerType(is_signed);2184ParseChildEnumerators(clang_type, is_signed,2185type->GetByteSize(nullptr).value_or(0), die);2186}2187TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);2188}2189return (bool)clang_type;2190}21912192bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,2193lldb_private::Type *type,2194CompilerType &clang_type) {2195SymbolFileDWARF *dwarf = die.GetDWARF();21962197std::lock_guard<std::recursive_mutex> guard(2198dwarf->GetObjectFile()->GetModule()->GetMutex());21992200// Disable external storage for this type so we don't get anymore2201// clang::ExternalASTSource queries for this type.2202m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), false);22032204if (!die)2205return false;22062207const dw_tag_t tag = die.Tag();22082209assert(clang_type);2210switch (tag) {2211case DW_TAG_structure_type:2212case DW_TAG_union_type:2213case DW_TAG_class_type:2214CompleteRecordType(die, type, clang_type);2215break;2216case DW_TAG_enumeration_type:2217CompleteEnumType(die, type, clang_type);2218break;2219default:2220assert(false && "not a forward clang type decl!");2221break;2222}22232224// If the type is still not fully defined at this point, it means we weren't2225// able to find its definition. We must forcefully complete it to preserve2226// clang AST invariants.2227if (clang_type.IsBeingDefined()) {2228TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);2229m_ast.SetDeclIsForcefullyCompleted(ClangUtil::GetAsTagDecl(clang_type));2230}22312232return true;2233}22342235void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed(2236lldb_private::CompilerDeclContext decl_context) {2237auto opaque_decl_ctx =2238(clang::DeclContext *)decl_context.GetOpaqueDeclContext();2239for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx);2240it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx;2241it = m_decl_ctx_to_die.erase(it))2242for (DWARFDIE decl : it->second.children())2243GetClangDeclForDIE(decl);2244}22452246CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) {2247clang::Decl *clang_decl = GetClangDeclForDIE(die);2248if (clang_decl != nullptr)2249return m_ast.GetCompilerDecl(clang_decl);2250return {};2251}22522253CompilerDeclContext2254DWARFASTParserClang::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {2255clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE(die);2256if (clang_decl_ctx)2257return m_ast.CreateDeclContext(clang_decl_ctx);2258return {};2259}22602261CompilerDeclContext2262DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {2263clang::DeclContext *clang_decl_ctx =2264GetClangDeclContextContainingDIE(die, nullptr);2265if (clang_decl_ctx)2266return m_ast.CreateDeclContext(clang_decl_ctx);2267return {};2268}22692270size_t DWARFASTParserClang::ParseChildEnumerators(2271lldb_private::CompilerType &clang_type, bool is_signed,2272uint32_t enumerator_byte_size, const DWARFDIE &parent_die) {2273if (!parent_die)2274return 0;22752276size_t enumerators_added = 0;22772278for (DWARFDIE die : parent_die.children()) {2279const dw_tag_t tag = die.Tag();2280if (tag != DW_TAG_enumerator)2281continue;22822283DWARFAttributes attributes = die.GetAttributes();2284if (attributes.Size() == 0)2285continue;22862287const char *name = nullptr;2288bool got_value = false;2289int64_t enum_value = 0;2290Declaration decl;22912292for (size_t i = 0; i < attributes.Size(); ++i) {2293const dw_attr_t attr = attributes.AttributeAtIndex(i);2294DWARFFormValue form_value;2295if (attributes.ExtractFormValueAtIndex(i, form_value)) {2296switch (attr) {2297case DW_AT_const_value:2298got_value = true;2299if (is_signed)2300enum_value = form_value.Signed();2301else2302enum_value = form_value.Unsigned();2303break;23042305case DW_AT_name:2306name = form_value.AsCString();2307break;23082309case DW_AT_description:2310default:2311case DW_AT_decl_file:2312decl.SetFile(2313attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));2314break;2315case DW_AT_decl_line:2316decl.SetLine(form_value.Unsigned());2317break;2318case DW_AT_decl_column:2319decl.SetColumn(form_value.Unsigned());2320break;2321case DW_AT_sibling:2322break;2323}2324}2325}23262327if (name && name[0] && got_value) {2328m_ast.AddEnumerationValueToEnumerationType(2329clang_type, decl, name, enum_value, enumerator_byte_size * 8);2330++enumerators_added;2331}2332}2333return enumerators_added;2334}23352336ConstString2337DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {2338bool is_static = false;2339bool is_variadic = false;2340bool has_template_params = false;2341unsigned type_quals = 0;2342std::vector<CompilerType> param_types;2343std::vector<clang::ParmVarDecl *> param_decls;2344StreamString sstr;23452346DWARFDeclContext decl_ctx = die.GetDWARFDeclContext();2347sstr << decl_ctx.GetQualifiedName();23482349clang::DeclContext *containing_decl_ctx =2350GetClangDeclContextContainingDIE(die, nullptr);2351ParseChildParameters(containing_decl_ctx, die, true, is_static, is_variadic,2352has_template_params, param_types, param_decls,2353type_quals);2354sstr << "(";2355for (size_t i = 0; i < param_types.size(); i++) {2356if (i > 0)2357sstr << ", ";2358sstr << param_types[i].GetTypeName();2359}2360if (is_variadic)2361sstr << ", ...";2362sstr << ")";2363if (type_quals & clang::Qualifiers::Const)2364sstr << " const";23652366return ConstString(sstr.GetString());2367}23682369Function *2370DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,2371const DWARFDIE &die,2372const AddressRange &func_range) {2373assert(func_range.GetBaseAddress().IsValid());2374DWARFRangeList func_ranges;2375const char *name = nullptr;2376const char *mangled = nullptr;2377std::optional<int> decl_file;2378std::optional<int> decl_line;2379std::optional<int> decl_column;2380std::optional<int> call_file;2381std::optional<int> call_line;2382std::optional<int> call_column;2383DWARFExpressionList frame_base;23842385const dw_tag_t tag = die.Tag();23862387if (tag != DW_TAG_subprogram)2388return nullptr;23892390if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,2391decl_column, call_file, call_line, call_column,2392&frame_base)) {2393Mangled func_name;2394if (mangled)2395func_name.SetValue(ConstString(mangled));2396else if ((die.GetParent().Tag() == DW_TAG_compile_unit ||2397die.GetParent().Tag() == DW_TAG_partial_unit) &&2398Language::LanguageIsCPlusPlus(2399SymbolFileDWARF::GetLanguage(*die.GetCU())) &&2400!Language::LanguageIsObjC(2401SymbolFileDWARF::GetLanguage(*die.GetCU())) &&2402name && strcmp(name, "main") != 0) {2403// If the mangled name is not present in the DWARF, generate the2404// demangled name using the decl context. We skip if the function is2405// "main" as its name is never mangled.2406func_name.SetValue(ConstructDemangledNameFromDWARF(die));2407} else2408func_name.SetValue(ConstString(name));24092410FunctionSP func_sp;2411std::unique_ptr<Declaration> decl_up;2412if (decl_file || decl_line || decl_column)2413decl_up = std::make_unique<Declaration>(2414die.GetCU()->GetFile(decl_file ? *decl_file : 0),2415decl_line ? *decl_line : 0, decl_column ? *decl_column : 0);24162417SymbolFileDWARF *dwarf = die.GetDWARF();2418// Supply the type _only_ if it has already been parsed2419Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE());24202421assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);24222423const user_id_t func_user_id = die.GetID();2424func_sp =2425std::make_shared<Function>(&comp_unit,2426func_user_id, // UserID is the DIE offset2427func_user_id, func_name, func_type,2428func_range); // first address range24292430if (func_sp.get() != nullptr) {2431if (frame_base.IsValid())2432func_sp->GetFrameBaseExpression() = frame_base;2433comp_unit.AddFunction(func_sp);2434return func_sp.get();2435}2436}2437return nullptr;2438}24392440namespace {2441/// Parsed form of all attributes that are relevant for parsing Objective-C2442/// properties.2443struct PropertyAttributes {2444explicit PropertyAttributes(const DWARFDIE &die);2445const char *prop_name = nullptr;2446const char *prop_getter_name = nullptr;2447const char *prop_setter_name = nullptr;2448/// \see clang::ObjCPropertyAttribute2449uint32_t prop_attributes = 0;2450};24512452struct DiscriminantValue {2453explicit DiscriminantValue(const DWARFDIE &die, ModuleSP module_sp);24542455uint32_t byte_offset;2456uint32_t byte_size;2457DWARFFormValue type_ref;2458};24592460struct VariantMember {2461explicit VariantMember(DWARFDIE &die, ModuleSP module_sp);2462bool IsDefault() const;24632464std::optional<uint32_t> discr_value;2465DWARFFormValue type_ref;2466ConstString variant_name;2467uint32_t byte_offset;2468ConstString GetName() const;2469};24702471struct VariantPart {2472explicit VariantPart(const DWARFDIE &die, const DWARFDIE &parent_die,2473ModuleSP module_sp);24742475std::vector<VariantMember> &members();24762477DiscriminantValue &discriminant();24782479private:2480std::vector<VariantMember> _members;2481DiscriminantValue _discriminant;2482};24832484} // namespace24852486ConstString VariantMember::GetName() const { return this->variant_name; }24872488bool VariantMember::IsDefault() const { return !discr_value; }24892490VariantMember::VariantMember(DWARFDIE &die, lldb::ModuleSP module_sp) {2491assert(die.Tag() == llvm::dwarf::DW_TAG_variant);2492this->discr_value =2493die.GetAttributeValueAsOptionalUnsigned(DW_AT_discr_value);24942495for (auto child_die : die.children()) {2496switch (child_die.Tag()) {2497case llvm::dwarf::DW_TAG_member: {2498DWARFAttributes attributes = child_die.GetAttributes();2499for (std::size_t i = 0; i < attributes.Size(); ++i) {2500DWARFFormValue form_value;2501const dw_attr_t attr = attributes.AttributeAtIndex(i);2502if (attributes.ExtractFormValueAtIndex(i, form_value)) {2503switch (attr) {2504case DW_AT_name:2505variant_name = ConstString(form_value.AsCString());2506break;2507case DW_AT_type:2508type_ref = form_value;2509break;25102511case DW_AT_data_member_location:2512if (auto maybe_offset =2513ExtractDataMemberLocation(die, form_value, module_sp))2514byte_offset = *maybe_offset;2515break;25162517default:2518break;2519}2520}2521}2522break;2523}2524default:2525break;2526}2527break;2528}2529}25302531DiscriminantValue::DiscriminantValue(const DWARFDIE &die, ModuleSP module_sp) {2532auto referenced_die = die.GetReferencedDIE(DW_AT_discr);2533DWARFAttributes attributes = referenced_die.GetAttributes();2534for (std::size_t i = 0; i < attributes.Size(); ++i) {2535const dw_attr_t attr = attributes.AttributeAtIndex(i);2536DWARFFormValue form_value;2537if (attributes.ExtractFormValueAtIndex(i, form_value)) {2538switch (attr) {2539case DW_AT_type:2540type_ref = form_value;2541break;2542case DW_AT_data_member_location:2543if (auto maybe_offset =2544ExtractDataMemberLocation(die, form_value, module_sp))2545byte_offset = *maybe_offset;2546break;2547default:2548break;2549}2550}2551}2552}25532554VariantPart::VariantPart(const DWARFDIE &die, const DWARFDIE &parent_die,2555lldb::ModuleSP module_sp)2556: _members(), _discriminant(die, module_sp) {25572558for (auto child : die.children()) {2559if (child.Tag() == llvm::dwarf::DW_TAG_variant) {2560_members.push_back(VariantMember(child, module_sp));2561}2562}2563}25642565std::vector<VariantMember> &VariantPart::members() { return this->_members; }25662567DiscriminantValue &VariantPart::discriminant() { return this->_discriminant; }25682569DWARFASTParserClang::MemberAttributes::MemberAttributes(2570const DWARFDIE &die, const DWARFDIE &parent_die, ModuleSP module_sp) {2571DWARFAttributes attributes = die.GetAttributes();2572for (size_t i = 0; i < attributes.Size(); ++i) {2573const dw_attr_t attr = attributes.AttributeAtIndex(i);2574DWARFFormValue form_value;2575if (attributes.ExtractFormValueAtIndex(i, form_value)) {2576switch (attr) {2577case DW_AT_name:2578name = form_value.AsCString();2579break;2580case DW_AT_type:2581encoding_form = form_value;2582break;2583case DW_AT_bit_offset:2584bit_offset = form_value.Signed();2585break;2586case DW_AT_bit_size:2587bit_size = form_value.Unsigned();2588break;2589case DW_AT_byte_size:2590byte_size = form_value.Unsigned();2591break;2592case DW_AT_const_value:2593const_value_form = form_value;2594break;2595case DW_AT_data_bit_offset:2596data_bit_offset = form_value.Unsigned();2597break;2598case DW_AT_data_member_location:2599if (auto maybe_offset =2600ExtractDataMemberLocation(die, form_value, module_sp))2601member_byte_offset = *maybe_offset;2602break;26032604case DW_AT_accessibility:2605accessibility =2606DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned());2607break;2608case DW_AT_artificial:2609is_artificial = form_value.Boolean();2610break;2611case DW_AT_declaration:2612is_declaration = form_value.Boolean();2613break;2614default:2615break;2616}2617}2618}26192620// Clang has a DWARF generation bug where sometimes it represents2621// fields that are references with bad byte size and bit size/offset2622// information such as:2623//2624// DW_AT_byte_size( 0x00 )2625// DW_AT_bit_size( 0x40 )2626// DW_AT_bit_offset( 0xffffffffffffffc0 )2627//2628// So check the bit offset to make sure it is sane, and if the values2629// are not sane, remove them. If we don't do this then we will end up2630// with a crash if we try to use this type in an expression when clang2631// becomes unhappy with its recycled debug info.2632if (byte_size.value_or(0) == 0 && bit_offset < 0) {2633bit_size = 0;2634bit_offset = 0;2635}2636}26372638PropertyAttributes::PropertyAttributes(const DWARFDIE &die) {26392640DWARFAttributes attributes = die.GetAttributes();2641for (size_t i = 0; i < attributes.Size(); ++i) {2642const dw_attr_t attr = attributes.AttributeAtIndex(i);2643DWARFFormValue form_value;2644if (attributes.ExtractFormValueAtIndex(i, form_value)) {2645switch (attr) {2646case DW_AT_APPLE_property_name:2647prop_name = form_value.AsCString();2648break;2649case DW_AT_APPLE_property_getter:2650prop_getter_name = form_value.AsCString();2651break;2652case DW_AT_APPLE_property_setter:2653prop_setter_name = form_value.AsCString();2654break;2655case DW_AT_APPLE_property_attribute:2656prop_attributes = form_value.Unsigned();2657break;2658default:2659break;2660}2661}2662}26632664if (!prop_name)2665return;2666ConstString fixed_setter;26672668// Check if the property getter/setter were provided as full names.2669// We want basenames, so we extract them.2670if (prop_getter_name && prop_getter_name[0] == '-') {2671std::optional<const ObjCLanguage::MethodName> prop_getter_method =2672ObjCLanguage::MethodName::Create(prop_getter_name, true);2673if (prop_getter_method)2674prop_getter_name =2675ConstString(prop_getter_method->GetSelector()).GetCString();2676}26772678if (prop_setter_name && prop_setter_name[0] == '-') {2679std::optional<const ObjCLanguage::MethodName> prop_setter_method =2680ObjCLanguage::MethodName::Create(prop_setter_name, true);2681if (prop_setter_method)2682prop_setter_name =2683ConstString(prop_setter_method->GetSelector()).GetCString();2684}26852686// If the names haven't been provided, they need to be filled in.2687if (!prop_getter_name)2688prop_getter_name = prop_name;2689if (!prop_setter_name && prop_name[0] &&2690!(prop_attributes & DW_APPLE_PROPERTY_readonly)) {2691StreamString ss;26922693ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);26942695fixed_setter.SetString(ss.GetString());2696prop_setter_name = fixed_setter.GetCString();2697}2698}26992700void DWARFASTParserClang::ParseObjCProperty(2701const DWARFDIE &die, const DWARFDIE &parent_die,2702const lldb_private::CompilerType &class_clang_type,2703DelayedPropertyList &delayed_properties) {2704// This function can only parse DW_TAG_APPLE_property.2705assert(die.Tag() == DW_TAG_APPLE_property);27062707ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();27082709const MemberAttributes attrs(die, parent_die, module_sp);2710const PropertyAttributes propAttrs(die);27112712if (!propAttrs.prop_name) {2713module_sp->ReportError("{0:x8}: DW_TAG_APPLE_property has no name.",2714die.GetID());2715return;2716}27172718Type *member_type = die.ResolveTypeUID(attrs.encoding_form.Reference());2719if (!member_type) {2720module_sp->ReportError(2721"{0:x8}: DW_TAG_APPLE_property '{1}' refers to type {2:x16}"2722" which was unable to be parsed",2723die.GetID(), propAttrs.prop_name,2724attrs.encoding_form.Reference().GetOffset());2725return;2726}27272728ClangASTMetadata metadata;2729metadata.SetUserID(die.GetID());2730delayed_properties.push_back(DelayedAddObjCClassProperty(2731class_clang_type, propAttrs.prop_name,2732member_type->GetLayoutCompilerType(), propAttrs.prop_setter_name,2733propAttrs.prop_getter_name, propAttrs.prop_attributes, &metadata));2734}27352736llvm::Expected<llvm::APInt> DWARFASTParserClang::ExtractIntFromFormValue(2737const CompilerType &int_type, const DWARFFormValue &form_value) const {2738clang::QualType qt = ClangUtil::GetQualType(int_type);2739assert(qt->isIntegralOrEnumerationType());2740auto ts_ptr = int_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();2741if (!ts_ptr)2742return llvm::createStringError(llvm::inconvertibleErrorCode(),2743"TypeSystem not clang");2744TypeSystemClang &ts = *ts_ptr;2745clang::ASTContext &ast = ts.getASTContext();27462747const unsigned type_bits = ast.getIntWidth(qt);2748const bool is_unsigned = qt->isUnsignedIntegerType();27492750// The maximum int size supported at the moment by this function. Limited2751// by the uint64_t return type of DWARFFormValue::Signed/Unsigned.2752constexpr std::size_t max_bit_size = 64;27532754// For values bigger than 64 bit (e.g. __int128_t values),2755// DWARFFormValue's Signed/Unsigned functions will return wrong results so2756// emit an error for now.2757if (type_bits > max_bit_size) {2758auto msg = llvm::formatv("Can only parse integers with up to {0} bits, but "2759"given integer has {1} bits.",2760max_bit_size, type_bits);2761return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.str());2762}27632764// Construct an APInt with the maximum bit size and the given integer.2765llvm::APInt result(max_bit_size, form_value.Unsigned(), !is_unsigned);27662767// Calculate how many bits are required to represent the input value.2768// For unsigned types, take the number of active bits in the APInt.2769// For signed types, ask APInt how many bits are required to represent the2770// signed integer.2771const unsigned required_bits =2772is_unsigned ? result.getActiveBits() : result.getSignificantBits();27732774// If the input value doesn't fit into the integer type, return an error.2775if (required_bits > type_bits) {2776std::string value_as_str = is_unsigned2777? std::to_string(form_value.Unsigned())2778: std::to_string(form_value.Signed());2779auto msg = llvm::formatv("Can't store {0} value {1} in integer with {2} "2780"bits.",2781(is_unsigned ? "unsigned" : "signed"),2782value_as_str, type_bits);2783return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.str());2784}27852786// Trim the result to the bit width our the int type.2787if (result.getBitWidth() > type_bits)2788result = result.trunc(type_bits);2789return result;2790}27912792void DWARFASTParserClang::CreateStaticMemberVariable(2793const DWARFDIE &die, const MemberAttributes &attrs,2794const lldb_private::CompilerType &class_clang_type) {2795Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);2796assert(die.Tag() == DW_TAG_member || die.Tag() == DW_TAG_variable);27972798Type *var_type = die.ResolveTypeUID(attrs.encoding_form.Reference());27992800if (!var_type)2801return;28022803auto accessibility =2804attrs.accessibility == eAccessNone ? eAccessPublic : attrs.accessibility;28052806CompilerType ct = var_type->GetForwardCompilerType();2807clang::VarDecl *v = TypeSystemClang::AddVariableToRecordType(2808class_clang_type, attrs.name, ct, accessibility);2809if (!v) {2810LLDB_LOG(log, "Failed to add variable to the record type");2811return;2812}28132814bool unused;2815// TODO: Support float/double static members as well.2816if (!ct.IsIntegerOrEnumerationType(unused) || !attrs.const_value_form)2817return;28182819llvm::Expected<llvm::APInt> const_value_or_err =2820ExtractIntFromFormValue(ct, *attrs.const_value_form);2821if (!const_value_or_err) {2822LLDB_LOG_ERROR(log, const_value_or_err.takeError(),2823"Failed to add const value to variable {1}: {0}",2824v->getQualifiedNameAsString());2825return;2826}28272828TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err);2829}28302831void DWARFASTParserClang::ParseSingleMember(2832const DWARFDIE &die, const DWARFDIE &parent_die,2833const lldb_private::CompilerType &class_clang_type,2834lldb::AccessType default_accessibility,2835lldb_private::ClangASTImporter::LayoutInfo &layout_info,2836FieldInfo &last_field_info) {2837// This function can only parse DW_TAG_member.2838assert(die.Tag() == DW_TAG_member);28392840ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();2841const dw_tag_t tag = die.Tag();2842// Get the parent byte size so we can verify any members will fit2843const uint64_t parent_byte_size =2844parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);2845const uint64_t parent_bit_size =2846parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8;28472848const MemberAttributes attrs(die, parent_die, module_sp);28492850// Handle static members, which are typically members without2851// locations. However, GCC doesn't emit DW_AT_data_member_location2852// for any union members (regardless of linkage).2853// Non-normative text pre-DWARFv5 recommends marking static2854// data members with an DW_AT_external flag. Clang emits this consistently2855// whereas GCC emits it only for static data members if not part of an2856// anonymous namespace. The flag that is consistently emitted for static2857// data members is DW_AT_declaration, so we check it instead.2858// The following block is only necessary to support DWARFv4 and earlier.2859// Starting with DWARFv5, static data members are marked DW_AT_variable so we2860// can consistently detect them on both GCC and Clang without below heuristic.2861if (attrs.member_byte_offset == UINT32_MAX &&2862attrs.data_bit_offset == UINT64_MAX && attrs.is_declaration) {2863CreateStaticMemberVariable(die, attrs, class_clang_type);2864return;2865}28662867Type *member_type = die.ResolveTypeUID(attrs.encoding_form.Reference());2868if (!member_type) {2869if (attrs.name)2870module_sp->ReportError(2871"{0:x8}: DW_TAG_member '{1}' refers to type {2:x16}"2872" which was unable to be parsed",2873die.GetID(), attrs.name, attrs.encoding_form.Reference().GetOffset());2874else2875module_sp->ReportError("{0:x8}: DW_TAG_member refers to type {1:x16}"2876" which was unable to be parsed",2877die.GetID(),2878attrs.encoding_form.Reference().GetOffset());2879return;2880}28812882const uint64_t character_width = 8;2883const uint64_t word_width = 32;2884CompilerType member_clang_type = member_type->GetLayoutCompilerType();28852886const auto accessibility = attrs.accessibility == eAccessNone2887? default_accessibility2888: attrs.accessibility;28892890uint64_t field_bit_offset = (attrs.member_byte_offset == UINT32_MAX2891? 02892: (attrs.member_byte_offset * 8ULL));28932894if (attrs.bit_size > 0) {2895FieldInfo this_field_info;2896this_field_info.bit_offset = field_bit_offset;2897this_field_info.bit_size = attrs.bit_size;28982899if (attrs.data_bit_offset != UINT64_MAX) {2900this_field_info.bit_offset = attrs.data_bit_offset;2901} else {2902auto byte_size = attrs.byte_size;2903if (!byte_size)2904byte_size = member_type->GetByteSize(nullptr);29052906ObjectFile *objfile = die.GetDWARF()->GetObjectFile();2907if (objfile->GetByteOrder() == eByteOrderLittle) {2908this_field_info.bit_offset += byte_size.value_or(0) * 8;2909this_field_info.bit_offset -= (attrs.bit_offset + attrs.bit_size);2910} else {2911this_field_info.bit_offset += attrs.bit_offset;2912}2913}29142915// The ObjC runtime knows the byte offset but we still need to provide2916// the bit-offset in the layout. It just means something different then2917// what it does in C and C++. So we skip this check for ObjC types.2918//2919// We also skip this for fields of a union since they will all have a2920// zero offset.2921if (!TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type) &&2922!(parent_die.Tag() == DW_TAG_union_type &&2923this_field_info.bit_offset == 0) &&2924((this_field_info.bit_offset >= parent_bit_size) ||2925(last_field_info.IsBitfield() &&2926!last_field_info.NextBitfieldOffsetIsValid(2927this_field_info.bit_offset)))) {2928ObjectFile *objfile = die.GetDWARF()->GetObjectFile();2929objfile->GetModule()->ReportWarning(2930"{0:x16}: {1} ({2}) bitfield named \"{3}\" has invalid "2931"bit offset ({4:x8}) member will be ignored. Please file a bug "2932"against the "2933"compiler and include the preprocessed output for {5}\n",2934die.GetID(), DW_TAG_value_to_name(tag), tag, attrs.name,2935this_field_info.bit_offset, GetUnitName(parent_die).c_str());2936return;2937}29382939// Update the field bit offset we will report for layout2940field_bit_offset = this_field_info.bit_offset;29412942// Objective-C has invalid DW_AT_bit_offset values in older2943// versions of clang, so we have to be careful and only insert2944// unnamed bitfields if we have a new enough clang.2945bool detect_unnamed_bitfields = true;29462947if (TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type))2948detect_unnamed_bitfields =2949die.GetCU()->Supports_unnamed_objc_bitfields();29502951if (detect_unnamed_bitfields) {2952std::optional<FieldInfo> unnamed_field_info;2953uint64_t last_field_end =2954last_field_info.bit_offset + last_field_info.bit_size;29552956if (!last_field_info.IsBitfield()) {2957// The last field was not a bit-field...2958// but if it did take up the entire word then we need to extend2959// last_field_end so the bit-field does not step into the last2960// fields padding.2961if (last_field_end != 0 && ((last_field_end % word_width) != 0))2962last_field_end += word_width - (last_field_end % word_width);2963}29642965if (ShouldCreateUnnamedBitfield(last_field_info, last_field_end,2966this_field_info, layout_info)) {2967unnamed_field_info = FieldInfo{};2968unnamed_field_info->bit_size =2969this_field_info.bit_offset - last_field_end;2970unnamed_field_info->bit_offset = last_field_end;2971}29722973if (unnamed_field_info) {2974clang::FieldDecl *unnamed_bitfield_decl =2975TypeSystemClang::AddFieldToRecordType(2976class_clang_type, llvm::StringRef(),2977m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,2978word_width),2979accessibility, unnamed_field_info->bit_size);29802981layout_info.field_offsets.insert(std::make_pair(2982unnamed_bitfield_decl, unnamed_field_info->bit_offset));2983}2984}29852986last_field_info = this_field_info;2987last_field_info.SetIsBitfield(true);2988} else {2989last_field_info.bit_offset = field_bit_offset;29902991if (std::optional<uint64_t> clang_type_size =2992member_type->GetByteSize(nullptr)) {2993last_field_info.bit_size = *clang_type_size * character_width;2994}29952996last_field_info.SetIsBitfield(false);2997}29982999// Don't turn artificial members such as vtable pointers into real FieldDecls3000// in our AST. Clang will re-create those articial members and they would3001// otherwise just overlap in the layout with the FieldDecls we add here.3002// This needs to be done after updating FieldInfo which keeps track of where3003// field start/end so we don't later try to fill the space of this3004// artificial member with (unnamed bitfield) padding.3005if (attrs.is_artificial && ShouldIgnoreArtificialField(attrs.name)) {3006last_field_info.SetIsArtificial(true);3007return;3008}30093010if (!member_clang_type.IsCompleteType())3011member_clang_type.GetCompleteType();30123013{3014// Older versions of clang emit the same DWARF for array[0] and array[1]. If3015// the current field is at the end of the structure, then there is3016// definitely no room for extra elements and we override the type to3017// array[0]. This was fixed by f454dfb6b5af.3018CompilerType member_array_element_type;3019uint64_t member_array_size;3020bool member_array_is_incomplete;30213022if (member_clang_type.IsArrayType(&member_array_element_type,3023&member_array_size,3024&member_array_is_incomplete) &&3025!member_array_is_incomplete) {3026uint64_t parent_byte_size =3027parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);30283029if (attrs.member_byte_offset >= parent_byte_size) {3030if (member_array_size != 1 &&3031(member_array_size != 0 ||3032attrs.member_byte_offset > parent_byte_size)) {3033module_sp->ReportError(3034"{0:x8}: DW_TAG_member '{1}' refers to type {2:x16}"3035" which extends beyond the bounds of {3:x8}",3036die.GetID(), attrs.name,3037attrs.encoding_form.Reference().GetOffset(), parent_die.GetID());3038}30393040member_clang_type =3041m_ast.CreateArrayType(member_array_element_type, 0, false);3042}3043}3044}30453046TypeSystemClang::RequireCompleteType(member_clang_type);30473048clang::FieldDecl *field_decl = TypeSystemClang::AddFieldToRecordType(3049class_clang_type, attrs.name, member_clang_type, accessibility,3050attrs.bit_size);30513052m_ast.SetMetadataAsUserID(field_decl, die.GetID());30533054layout_info.field_offsets.insert(3055std::make_pair(field_decl, field_bit_offset));3056}30573058bool DWARFASTParserClang::ParseChildMembers(3059const DWARFDIE &parent_die, CompilerType &class_clang_type,3060std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,3061std::vector<DWARFDIE> &member_function_dies,3062std::vector<DWARFDIE> &contained_type_dies,3063DelayedPropertyList &delayed_properties,3064const AccessType default_accessibility,3065ClangASTImporter::LayoutInfo &layout_info) {3066if (!parent_die)3067return false;30683069FieldInfo last_field_info;30703071ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();3072auto ts = class_clang_type.GetTypeSystem();3073auto ast = ts.dyn_cast_or_null<TypeSystemClang>();3074if (ast == nullptr)3075return false;30763077for (DWARFDIE die : parent_die.children()) {3078dw_tag_t tag = die.Tag();30793080switch (tag) {3081case DW_TAG_APPLE_property:3082ParseObjCProperty(die, parent_die, class_clang_type, delayed_properties);3083break;30843085case DW_TAG_variant_part:3086if (die.GetCU()->GetDWARFLanguageType() == eLanguageTypeRust) {3087ParseRustVariantPart(die, parent_die, class_clang_type,3088default_accessibility, layout_info);3089}3090break;30913092case DW_TAG_variable: {3093const MemberAttributes attrs(die, parent_die, module_sp);3094CreateStaticMemberVariable(die, attrs, class_clang_type);3095} break;3096case DW_TAG_member:3097ParseSingleMember(die, parent_die, class_clang_type,3098default_accessibility, layout_info, last_field_info);3099break;31003101case DW_TAG_subprogram:3102// Let the type parsing code handle this one for us.3103member_function_dies.push_back(die);3104break;31053106case DW_TAG_inheritance:3107ParseInheritance(die, parent_die, class_clang_type, default_accessibility,3108module_sp, base_classes, layout_info);3109break;31103111default:3112if (llvm::dwarf::isType(tag))3113contained_type_dies.push_back(die);3114break;3115}3116}31173118return true;3119}31203121size_t DWARFASTParserClang::ParseChildParameters(3122clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die,3123bool skip_artificial, bool &is_static, bool &is_variadic,3124bool &has_template_params, std::vector<CompilerType> &function_param_types,3125std::vector<clang::ParmVarDecl *> &function_param_decls,3126unsigned &type_quals) {3127if (!parent_die)3128return 0;31293130size_t arg_idx = 0;3131for (DWARFDIE die : parent_die.children()) {3132const dw_tag_t tag = die.Tag();3133switch (tag) {3134case DW_TAG_formal_parameter: {3135DWARFAttributes attributes = die.GetAttributes();3136if (attributes.Size() == 0) {3137arg_idx++;3138break;3139}31403141const char *name = nullptr;3142DWARFFormValue param_type_die_form;3143bool is_artificial = false;3144// one of None, Auto, Register, Extern, Static, PrivateExtern31453146clang::StorageClass storage = clang::SC_None;3147uint32_t i;3148for (i = 0; i < attributes.Size(); ++i) {3149const dw_attr_t attr = attributes.AttributeAtIndex(i);3150DWARFFormValue form_value;3151if (attributes.ExtractFormValueAtIndex(i, form_value)) {3152switch (attr) {3153case DW_AT_name:3154name = form_value.AsCString();3155break;3156case DW_AT_type:3157param_type_die_form = form_value;3158break;3159case DW_AT_artificial:3160is_artificial = form_value.Boolean();3161break;3162case DW_AT_location:3163case DW_AT_const_value:3164case DW_AT_default_value:3165case DW_AT_description:3166case DW_AT_endianity:3167case DW_AT_is_optional:3168case DW_AT_segment:3169case DW_AT_variable_parameter:3170default:3171case DW_AT_abstract_origin:3172case DW_AT_sibling:3173break;3174}3175}3176}31773178bool skip = false;3179if (skip_artificial && is_artificial) {3180// In order to determine if a C++ member function is "const" we3181// have to look at the const-ness of "this"...3182if (arg_idx == 0 &&3183DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()) &&3184// Often times compilers omit the "this" name for the3185// specification DIEs, so we can't rely upon the name being in3186// the formal parameter DIE...3187(name == nullptr || ::strcmp(name, "this") == 0)) {3188Type *this_type = die.ResolveTypeUID(param_type_die_form.Reference());3189if (this_type) {3190uint32_t encoding_mask = this_type->GetEncodingMask();3191if (encoding_mask & Type::eEncodingIsPointerUID) {3192is_static = false;31933194if (encoding_mask & (1u << Type::eEncodingIsConstUID))3195type_quals |= clang::Qualifiers::Const;3196if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))3197type_quals |= clang::Qualifiers::Volatile;3198}3199}3200}3201skip = true;3202}32033204if (!skip) {3205Type *type = die.ResolveTypeUID(param_type_die_form.Reference());3206if (type) {3207function_param_types.push_back(type->GetForwardCompilerType());32083209clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration(3210containing_decl_ctx, GetOwningClangModule(die), name,3211type->GetForwardCompilerType(), storage);3212assert(param_var_decl);3213function_param_decls.push_back(param_var_decl);32143215m_ast.SetMetadataAsUserID(param_var_decl, die.GetID());3216}3217}3218arg_idx++;3219} break;32203221case DW_TAG_unspecified_parameters:3222is_variadic = true;3223break;32243225case DW_TAG_template_type_parameter:3226case DW_TAG_template_value_parameter:3227case DW_TAG_GNU_template_parameter_pack:3228// The one caller of this was never using the template_param_infos, and3229// the local variable was taking up a large amount of stack space in3230// SymbolFileDWARF::ParseType() so this was removed. If we ever need the3231// template params back, we can add them back.3232// ParseTemplateDIE (dwarf_cu, die, template_param_infos);3233has_template_params = true;3234break;32353236default:3237break;3238}3239}3240return arg_idx;3241}32423243clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) {3244if (!die)3245return nullptr;32463247switch (die.Tag()) {3248case DW_TAG_constant:3249case DW_TAG_formal_parameter:3250case DW_TAG_imported_declaration:3251case DW_TAG_imported_module:3252break;3253case DW_TAG_variable:3254// This means 'die' is a C++ static data member.3255// We don't want to create decls for such members3256// here.3257if (auto parent = die.GetParent();3258parent.IsValid() && TagIsRecordType(parent.Tag()))3259return nullptr;3260break;3261default:3262return nullptr;3263}32643265DIEToDeclMap::iterator cache_pos = m_die_to_decl.find(die.GetDIE());3266if (cache_pos != m_die_to_decl.end())3267return cache_pos->second;32683269if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) {3270clang::Decl *decl = GetClangDeclForDIE(spec_die);3271m_die_to_decl[die.GetDIE()] = decl;3272return decl;3273}32743275if (DWARFDIE abstract_origin_die =3276die.GetReferencedDIE(DW_AT_abstract_origin)) {3277clang::Decl *decl = GetClangDeclForDIE(abstract_origin_die);3278m_die_to_decl[die.GetDIE()] = decl;3279return decl;3280}32813282clang::Decl *decl = nullptr;3283switch (die.Tag()) {3284case DW_TAG_variable:3285case DW_TAG_constant:3286case DW_TAG_formal_parameter: {3287SymbolFileDWARF *dwarf = die.GetDWARF();3288Type *type = GetTypeForDIE(die);3289if (dwarf && type) {3290const char *name = die.GetName();3291clang::DeclContext *decl_context =3292TypeSystemClang::DeclContextGetAsDeclContext(3293dwarf->GetDeclContextContainingUID(die.GetID()));3294decl = m_ast.CreateVariableDeclaration(3295decl_context, GetOwningClangModule(die), name,3296ClangUtil::GetQualType(type->GetForwardCompilerType()));3297}3298break;3299}3300case DW_TAG_imported_declaration: {3301SymbolFileDWARF *dwarf = die.GetDWARF();3302DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import);3303if (imported_uid) {3304CompilerDecl imported_decl = SymbolFileDWARF::GetDecl(imported_uid);3305if (imported_decl) {3306clang::DeclContext *decl_context =3307TypeSystemClang::DeclContextGetAsDeclContext(3308dwarf->GetDeclContextContainingUID(die.GetID()));3309if (clang::NamedDecl *clang_imported_decl =3310llvm::dyn_cast<clang::NamedDecl>(3311(clang::Decl *)imported_decl.GetOpaqueDecl()))3312decl = m_ast.CreateUsingDeclaration(3313decl_context, OptionalClangModuleID(), clang_imported_decl);3314}3315}3316break;3317}3318case DW_TAG_imported_module: {3319SymbolFileDWARF *dwarf = die.GetDWARF();3320DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import);33213322if (imported_uid) {3323CompilerDeclContext imported_decl_ctx =3324SymbolFileDWARF::GetDeclContext(imported_uid);3325if (imported_decl_ctx) {3326clang::DeclContext *decl_context =3327TypeSystemClang::DeclContextGetAsDeclContext(3328dwarf->GetDeclContextContainingUID(die.GetID()));3329if (clang::NamespaceDecl *ns_decl =3330TypeSystemClang::DeclContextGetAsNamespaceDecl(3331imported_decl_ctx))3332decl = m_ast.CreateUsingDirectiveDeclaration(3333decl_context, OptionalClangModuleID(), ns_decl);3334}3335}3336break;3337}3338default:3339break;3340}33413342m_die_to_decl[die.GetDIE()] = decl;33433344return decl;3345}33463347clang::DeclContext *3348DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {3349if (die) {3350clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE(die);3351if (decl_ctx)3352return decl_ctx;33533354bool try_parsing_type = true;3355switch (die.Tag()) {3356case DW_TAG_compile_unit:3357case DW_TAG_partial_unit:3358decl_ctx = m_ast.GetTranslationUnitDecl();3359try_parsing_type = false;3360break;33613362case DW_TAG_namespace:3363decl_ctx = ResolveNamespaceDIE(die);3364try_parsing_type = false;3365break;33663367case DW_TAG_imported_declaration:3368decl_ctx = ResolveImportedDeclarationDIE(die);3369try_parsing_type = false;3370break;33713372case DW_TAG_lexical_block:3373decl_ctx = GetDeclContextForBlock(die);3374try_parsing_type = false;3375break;33763377default:3378break;3379}33803381if (decl_ctx == nullptr && try_parsing_type) {3382Type *type = die.GetDWARF()->ResolveType(die);3383if (type)3384decl_ctx = GetCachedClangDeclContextForDIE(die);3385}33863387if (decl_ctx) {3388LinkDeclContextToDIE(decl_ctx, die);3389return decl_ctx;3390}3391}3392return nullptr;3393}33943395OptionalClangModuleID3396DWARFASTParserClang::GetOwningClangModule(const DWARFDIE &die) {3397if (!die.IsValid())3398return {};33993400for (DWARFDIE parent = die.GetParent(); parent.IsValid();3401parent = parent.GetParent()) {3402const dw_tag_t tag = parent.Tag();3403if (tag == DW_TAG_module) {3404DWARFDIE module_die = parent;3405auto it = m_die_to_module.find(module_die.GetDIE());3406if (it != m_die_to_module.end())3407return it->second;3408const char *name =3409module_die.GetAttributeValueAsString(DW_AT_name, nullptr);3410if (!name)3411return {};34123413OptionalClangModuleID id =3414m_ast.GetOrCreateClangModule(name, GetOwningClangModule(module_die));3415m_die_to_module.insert({module_die.GetDIE(), id});3416return id;3417}3418}3419return {};3420}34213422static bool IsSubroutine(const DWARFDIE &die) {3423switch (die.Tag()) {3424case DW_TAG_subprogram:3425case DW_TAG_inlined_subroutine:3426return true;3427default:3428return false;3429}3430}34313432static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) {3433for (DWARFDIE candidate = die; candidate; candidate = candidate.GetParent()) {3434if (IsSubroutine(candidate)) {3435if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {3436return candidate;3437} else {3438return DWARFDIE();3439}3440}3441}3442assert(0 && "Shouldn't call GetContainingFunctionWithAbstractOrigin on "3443"something not in a function");3444return DWARFDIE();3445}34463447static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) {3448for (DWARFDIE candidate : context.children()) {3449if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {3450return candidate;3451}3452}3453return DWARFDIE();3454}34553456static DWARFDIE FindFirstChildWithAbstractOrigin(const DWARFDIE &block,3457const DWARFDIE &function) {3458assert(IsSubroutine(function));3459for (DWARFDIE context = block; context != function.GetParent();3460context = context.GetParent()) {3461assert(!IsSubroutine(context) || context == function);3462if (DWARFDIE child = FindAnyChildWithAbstractOrigin(context)) {3463return child;3464}3465}3466return DWARFDIE();3467}34683469clang::DeclContext *3470DWARFASTParserClang::GetDeclContextForBlock(const DWARFDIE &die) {3471assert(die.Tag() == DW_TAG_lexical_block);3472DWARFDIE containing_function_with_abstract_origin =3473GetContainingFunctionWithAbstractOrigin(die);3474if (!containing_function_with_abstract_origin) {3475return (clang::DeclContext *)ResolveBlockDIE(die);3476}3477DWARFDIE child = FindFirstChildWithAbstractOrigin(3478die, containing_function_with_abstract_origin);3479CompilerDeclContext decl_context =3480GetDeclContextContainingUIDFromDWARF(child);3481return (clang::DeclContext *)decl_context.GetOpaqueDeclContext();3482}34833484clang::BlockDecl *DWARFASTParserClang::ResolveBlockDIE(const DWARFDIE &die) {3485if (die && die.Tag() == DW_TAG_lexical_block) {3486clang::BlockDecl *decl =3487llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]);34883489if (!decl) {3490DWARFDIE decl_context_die;3491clang::DeclContext *decl_context =3492GetClangDeclContextContainingDIE(die, &decl_context_die);3493decl =3494m_ast.CreateBlockDeclaration(decl_context, GetOwningClangModule(die));34953496if (decl)3497LinkDeclContextToDIE((clang::DeclContext *)decl, die);3498}34993500return decl;3501}3502return nullptr;3503}35043505clang::NamespaceDecl *3506DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {3507if (die && die.Tag() == DW_TAG_namespace) {3508// See if we already parsed this namespace DIE and associated it with a3509// uniqued namespace declaration3510clang::NamespaceDecl *namespace_decl =3511static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die.GetDIE()]);3512if (namespace_decl)3513return namespace_decl;3514else {3515const char *namespace_name = die.GetName();3516clang::DeclContext *containing_decl_ctx =3517GetClangDeclContextContainingDIE(die, nullptr);3518bool is_inline =3519die.GetAttributeValueAsUnsigned(DW_AT_export_symbols, 0) != 0;35203521namespace_decl = m_ast.GetUniqueNamespaceDeclaration(3522namespace_name, containing_decl_ctx, GetOwningClangModule(die),3523is_inline);35243525if (namespace_decl)3526LinkDeclContextToDIE((clang::DeclContext *)namespace_decl, die);3527return namespace_decl;3528}3529}3530return nullptr;3531}35323533clang::NamespaceDecl *3534DWARFASTParserClang::ResolveImportedDeclarationDIE(const DWARFDIE &die) {3535assert(die && die.Tag() == DW_TAG_imported_declaration);35363537// See if we cached a NamespaceDecl for this imported declaration3538// already3539auto it = m_die_to_decl_ctx.find(die.GetDIE());3540if (it != m_die_to_decl_ctx.end())3541return static_cast<clang::NamespaceDecl *>(it->getSecond());35423543clang::NamespaceDecl *namespace_decl = nullptr;35443545const DWARFDIE imported_uid =3546die.GetAttributeValueAsReferenceDIE(DW_AT_import);3547if (!imported_uid)3548return nullptr;35493550switch (imported_uid.Tag()) {3551case DW_TAG_imported_declaration:3552namespace_decl = ResolveImportedDeclarationDIE(imported_uid);3553break;3554case DW_TAG_namespace:3555namespace_decl = ResolveNamespaceDIE(imported_uid);3556break;3557default:3558return nullptr;3559}35603561if (!namespace_decl)3562return nullptr;35633564LinkDeclContextToDIE(namespace_decl, die);35653566return namespace_decl;3567}35683569clang::DeclContext *DWARFASTParserClang::GetClangDeclContextContainingDIE(3570const DWARFDIE &die, DWARFDIE *decl_ctx_die_copy) {3571SymbolFileDWARF *dwarf = die.GetDWARF();35723573DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE(die);35743575if (decl_ctx_die_copy)3576*decl_ctx_die_copy = decl_ctx_die;35773578if (decl_ctx_die) {3579clang::DeclContext *clang_decl_ctx =3580GetClangDeclContextForDIE(decl_ctx_die);3581if (clang_decl_ctx)3582return clang_decl_ctx;3583}3584return m_ast.GetTranslationUnitDecl();3585}35863587clang::DeclContext *3588DWARFASTParserClang::GetCachedClangDeclContextForDIE(const DWARFDIE &die) {3589if (die) {3590DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE());3591if (pos != m_die_to_decl_ctx.end())3592return pos->second;3593}3594return nullptr;3595}35963597void DWARFASTParserClang::LinkDeclContextToDIE(clang::DeclContext *decl_ctx,3598const DWARFDIE &die) {3599m_die_to_decl_ctx[die.GetDIE()] = decl_ctx;3600// There can be many DIEs for a single decl context3601// m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE());3602m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die));3603}36043605bool DWARFASTParserClang::CopyUniqueClassMethodTypes(3606const DWARFDIE &src_class_die, const DWARFDIE &dst_class_die,3607lldb_private::Type *class_type, std::vector<DWARFDIE> &failures) {3608if (!class_type || !src_class_die || !dst_class_die)3609return false;3610if (src_class_die.Tag() != dst_class_die.Tag())3611return false;36123613// We need to complete the class type so we can get all of the method types3614// parsed so we can then unique those types to their equivalent counterparts3615// in "dst_cu" and "dst_class_die"3616class_type->GetFullCompilerType();36173618auto gather = [](DWARFDIE die, UniqueCStringMap<DWARFDIE> &map,3619UniqueCStringMap<DWARFDIE> &map_artificial) {3620if (die.Tag() != DW_TAG_subprogram)3621return;3622// Make sure this is a declaration and not a concrete instance by looking3623// for DW_AT_declaration set to 1. Sometimes concrete function instances are3624// placed inside the class definitions and shouldn't be included in the list3625// of things that are tracking here.3626if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) != 1)3627return;36283629if (const char *name = die.GetMangledName()) {3630ConstString const_name(name);3631if (die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))3632map_artificial.Append(const_name, die);3633else3634map.Append(const_name, die);3635}3636};36373638UniqueCStringMap<DWARFDIE> src_name_to_die;3639UniqueCStringMap<DWARFDIE> dst_name_to_die;3640UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;3641UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial;3642for (DWARFDIE src_die = src_class_die.GetFirstChild(); src_die.IsValid();3643src_die = src_die.GetSibling()) {3644gather(src_die, src_name_to_die, src_name_to_die_artificial);3645}3646for (DWARFDIE dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid();3647dst_die = dst_die.GetSibling()) {3648gather(dst_die, dst_name_to_die, dst_name_to_die_artificial);3649}3650const uint32_t src_size = src_name_to_die.GetSize();3651const uint32_t dst_size = dst_name_to_die.GetSize();36523653// Is everything kosher so we can go through the members at top speed?3654bool fast_path = true;36553656if (src_size != dst_size)3657fast_path = false;36583659uint32_t idx;36603661if (fast_path) {3662for (idx = 0; idx < src_size; ++idx) {3663DWARFDIE src_die = src_name_to_die.GetValueAtIndexUnchecked(idx);3664DWARFDIE dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);36653666if (src_die.Tag() != dst_die.Tag())3667fast_path = false;36683669const char *src_name = src_die.GetMangledName();3670const char *dst_name = dst_die.GetMangledName();36713672// Make sure the names match3673if (src_name == dst_name || (strcmp(src_name, dst_name) == 0))3674continue;36753676fast_path = false;3677}3678}36793680DWARFASTParserClang *src_dwarf_ast_parser =3681static_cast<DWARFASTParserClang *>(3682SymbolFileDWARF::GetDWARFParser(*src_class_die.GetCU()));3683DWARFASTParserClang *dst_dwarf_ast_parser =3684static_cast<DWARFASTParserClang *>(3685SymbolFileDWARF::GetDWARFParser(*dst_class_die.GetCU()));3686auto link = [&](DWARFDIE src, DWARFDIE dst) {3687SymbolFileDWARF::DIEToTypePtr &die_to_type =3688dst_class_die.GetDWARF()->GetDIEToType();3689clang::DeclContext *dst_decl_ctx =3690dst_dwarf_ast_parser->m_die_to_decl_ctx[dst.GetDIE()];3691if (dst_decl_ctx)3692src_dwarf_ast_parser->LinkDeclContextToDIE(dst_decl_ctx, src);36933694if (Type *src_child_type = die_to_type.lookup(src.GetDIE()))3695die_to_type[dst.GetDIE()] = src_child_type;3696};36973698// Now do the work of linking the DeclContexts and Types.3699if (fast_path) {3700// We can do this quickly. Just run across the tables index-for-index3701// since we know each node has matching names and tags.3702for (idx = 0; idx < src_size; ++idx) {3703link(src_name_to_die.GetValueAtIndexUnchecked(idx),3704dst_name_to_die.GetValueAtIndexUnchecked(idx));3705}3706} else {3707// We must do this slowly. For each member of the destination, look up a3708// member in the source with the same name, check its tag, and unique them3709// if everything matches up. Report failures.37103711if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) {3712src_name_to_die.Sort();37133714for (idx = 0; idx < dst_size; ++idx) {3715ConstString dst_name = dst_name_to_die.GetCStringAtIndex(idx);3716DWARFDIE dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);3717DWARFDIE src_die = src_name_to_die.Find(dst_name, DWARFDIE());37183719if (src_die && (src_die.Tag() == dst_die.Tag()))3720link(src_die, dst_die);3721else3722failures.push_back(dst_die);3723}3724}3725}37263727const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize();3728const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize();37293730if (src_size_artificial && dst_size_artificial) {3731dst_name_to_die_artificial.Sort();37323733for (idx = 0; idx < src_size_artificial; ++idx) {3734ConstString src_name_artificial =3735src_name_to_die_artificial.GetCStringAtIndex(idx);3736DWARFDIE src_die =3737src_name_to_die_artificial.GetValueAtIndexUnchecked(idx);3738DWARFDIE dst_die =3739dst_name_to_die_artificial.Find(src_name_artificial, DWARFDIE());37403741// Both classes have the artificial types, link them3742if (dst_die)3743link(src_die, dst_die);3744}3745}37463747if (dst_size_artificial) {3748for (idx = 0; idx < dst_size_artificial; ++idx) {3749failures.push_back(3750dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx));3751}3752}37533754return !failures.empty();3755}37563757bool DWARFASTParserClang::ShouldCreateUnnamedBitfield(3758FieldInfo const &last_field_info, uint64_t last_field_end,3759FieldInfo const &this_field_info,3760lldb_private::ClangASTImporter::LayoutInfo const &layout_info) const {3761// If we have a gap between the last_field_end and the current3762// field we have an unnamed bit-field.3763if (this_field_info.bit_offset <= last_field_end)3764return false;37653766// If we have a base class, we assume there is no unnamed3767// bit-field if either of the following is true:3768// (a) this is the first field since the gap can be3769// attributed to the members from the base class.3770// FIXME: This assumption is not correct if the first field of3771// the derived class is indeed an unnamed bit-field. We currently3772// do not have the machinary to track the offset of the last field3773// of classes we have seen before, so we are not handling this case.3774// (b) Or, the first member of the derived class was a vtable pointer.3775// In this case we don't want to create an unnamed bitfield either3776// since those will be inserted by clang later.3777const bool have_base = layout_info.base_offsets.size() != 0;3778const bool this_is_first_field =3779last_field_info.bit_offset == 0 && last_field_info.bit_size == 0;3780const bool first_field_is_vptr =3781last_field_info.bit_offset == 0 && last_field_info.IsArtificial();37823783if (have_base && (this_is_first_field || first_field_is_vptr))3784return false;37853786return true;3787}37883789void DWARFASTParserClang::ParseRustVariantPart(3790DWARFDIE &die, const DWARFDIE &parent_die, CompilerType &class_clang_type,3791const lldb::AccessType default_accesibility,3792ClangASTImporter::LayoutInfo &layout_info) {3793assert(die.Tag() == llvm::dwarf::DW_TAG_variant_part);3794assert(SymbolFileDWARF::GetLanguage(*die.GetCU()) ==3795LanguageType::eLanguageTypeRust);37963797ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();37983799VariantPart variants(die, parent_die, module_sp);38003801auto discriminant_type =3802die.ResolveTypeUID(variants.discriminant().type_ref.Reference());38033804auto decl_context = m_ast.GetDeclContextForType(class_clang_type);38053806auto inner_holder = m_ast.CreateRecordType(3807decl_context, OptionalClangModuleID(), lldb::eAccessPublic,3808std::string(3809llvm::formatv("{0}$Inner", class_clang_type.GetTypeName(false))),3810llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeRust);3811m_ast.StartTagDeclarationDefinition(inner_holder);3812m_ast.SetIsPacked(inner_holder);38133814for (auto member : variants.members()) {38153816auto has_discriminant = !member.IsDefault();38173818auto member_type = die.ResolveTypeUID(member.type_ref.Reference());38193820auto field_type = m_ast.CreateRecordType(3821m_ast.GetDeclContextForType(inner_holder), OptionalClangModuleID(),3822lldb::eAccessPublic,3823std::string(llvm::formatv("{0}$Variant", member.GetName())),3824llvm::to_underlying(clang::TagTypeKind::Struct),3825lldb::eLanguageTypeRust);38263827m_ast.StartTagDeclarationDefinition(field_type);3828auto offset = member.byte_offset;38293830if (has_discriminant) {3831m_ast.AddFieldToRecordType(3832field_type, "$discr$", discriminant_type->GetFullCompilerType(),3833lldb::eAccessPublic, variants.discriminant().byte_offset);3834offset += discriminant_type->GetByteSize(nullptr).value_or(0);3835}38363837m_ast.AddFieldToRecordType(field_type, "value",3838member_type->GetFullCompilerType(),3839lldb::eAccessPublic, offset * 8);38403841m_ast.CompleteTagDeclarationDefinition(field_type);38423843auto name = has_discriminant3844? llvm::formatv("$variant${0}", member.discr_value.value())3845: std::string("$variant$");38463847auto variant_decl =3848m_ast.AddFieldToRecordType(inner_holder, llvm::StringRef(name),3849field_type, default_accesibility, 0);38503851layout_info.field_offsets.insert({variant_decl, 0});3852}38533854auto inner_field = m_ast.AddFieldToRecordType(class_clang_type,3855llvm::StringRef("$variants$"),3856inner_holder, eAccessPublic, 0);38573858m_ast.CompleteTagDeclarationDefinition(inner_holder);38593860layout_info.field_offsets.insert({inner_field, 0});3861}386238633864