Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -228,13 +228,169 @@ } } +namespace { +/// Parsed form of all attributes that are relevant for type reconstruction. +/// Some attributes are relevant for all kinds of types (declaration), while +/// others are only meaningful to a specific type (is_virtual) +struct ParsedTypeAttributes { + ParsedTypeAttributes(const DWARFDIE &die, CompileUnit &comp_unit); + + AccessType accessibility = eAccessNone; + bool is_artificial = false; + bool is_complete_objc_class = false; + bool is_explicit = false; + bool is_forward_declaration = false; + bool is_inline = false; + bool is_scoped_enum = false; + bool is_vector = false; + bool is_virtual = false; + clang::StorageClass storage = clang::SC_None; + const char *mangled_name = nullptr; + ConstString name; + Declaration decl; + DWARFDIE object_pointer; + DWARFFormValue abstract_origin; + DWARFFormValue containing_type; + DWARFFormValue signature; + DWARFFormValue specification; + DWARFFormValue type; + LanguageType class_language = eLanguageTypeUnknown; + llvm::Optional byte_size; + size_t calling_convention = llvm::dwarf::DW_CC_normal; + uint32_t bit_stride = 0; + uint32_t byte_stride = 0; + uint32_t encoding = 0; +}; +} // namespace + +ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die, + CompileUnit &comp_unit) { + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(i, form_value)) + continue; + switch (attr) { + case DW_AT_abstract_origin: + abstract_origin = form_value; + break; + + case DW_AT_accessibility: + accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); + break; + + case DW_AT_artificial: + is_artificial = form_value.Boolean(); + break; + + case DW_AT_bit_stride: + bit_stride = form_value.Unsigned(); + break; + + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + + case DW_AT_byte_stride: + byte_stride = form_value.Unsigned(); + break; + + case DW_AT_calling_convention: + calling_convention = form_value.Unsigned(); + break; + + case DW_AT_containing_type: + containing_type = form_value; + break; + + case DW_AT_decl_file: + decl.SetFile(comp_unit.GetSupportFiles().GetFileSpecAtIndex( + form_value.Unsigned())); + break; + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + + case DW_AT_declaration: + is_forward_declaration = form_value.Boolean(); + break; + + case DW_AT_encoding: + encoding = form_value.Unsigned(); + break; + + case DW_AT_enum_class: + is_scoped_enum = form_value.Boolean(); + break; + + case DW_AT_explicit: + is_explicit = form_value.Boolean(); + break; + + case DW_AT_external: + if (form_value.Unsigned()) + storage = clang::SC_Extern; + break; + + case DW_AT_inline: + is_inline = form_value.Boolean(); + break; + + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: + mangled_name = form_value.AsCString(); + break; + + case DW_AT_name: + name.SetCString(form_value.AsCString()); + break; + + case DW_AT_object_pointer: + object_pointer = form_value.Reference(); + break; + + case DW_AT_signature: + signature = form_value; + break; + + case DW_AT_specification: + specification = form_value; + break; + + case DW_AT_type: + type = form_value; + break; + + case DW_AT_virtuality: + is_virtual = form_value.Boolean(); + break; + + case DW_AT_APPLE_objc_complete_type: + is_complete_objc_class = form_value.Signed(); + break; + + case DW_AT_APPLE_runtime_class: + class_language = (LanguageType)form_value.Signed(); + break; + + case DW_AT_GNU_vector: + is_vector = form_value.Boolean(); + break; + } + } +} + TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, const DWARFDIE &die, Log *log, bool *type_is_new_ptr) { if (type_is_new_ptr) *type_is_new_ptr = false; - AccessType accessibility = eAccessNone; if (!die) return nullptr; SymbolFileDWARF *dwarf = die.GetDWARF(); @@ -260,8 +416,9 @@ // Set a bit that lets us know that we are currently parsing this dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - if (DWARFDIE signature_die = - die.GetAttributeValueAsReferenceDIE(DW_AT_signature)) { + ParsedTypeAttributes attrs(die, *sc.comp_unit); + + if (DWARFDIE signature_die = attrs.signature.Reference()) { if (TypeSP type_sp = ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) { dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); @@ -279,20 +436,11 @@ const dw_tag_t tag = die.Tag(); - bool is_forward_declaration = false; - DWARFAttributes attributes; - const char *type_name_cstr = NULL; - const char *mangled_name_cstr = NULL; - ConstString type_name_const_str; Type::ResolveState resolve_state = Type::eResolveStateUnresolved; - llvm::Optional byte_size; - Declaration decl; Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; CompilerType clang_type; - DWARFFormValue form_value; - dw_attr_t attr; TypeSP type_sp; LanguageType cu_language = die.GetLanguage(); switch (tag) { @@ -305,49 +453,7 @@ case DW_TAG_restrict_type: case DW_TAG_volatile_type: case DW_TAG_unspecified_type: { - const size_t num_attributes = die.GetAttributes(attributes); - uint32_t encoding = 0; - DWARFFormValue encoding_uid; - - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - if (type_name_cstr) - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - case DW_AT_encoding: - encoding = form_value.Unsigned(); - break; - case DW_AT_type: - encoding_uid = form_value; - break; - default: - case DW_AT_sibling: - break; - } - } - } - } - - if (tag == DW_TAG_typedef && encoding_uid.IsValid()) { + if (tag == DW_TAG_typedef && attrs.type.IsValid()) { // Try to parse a typedef from the DWO file first as modules can // contain typedef'ed structures that have no names like: // @@ -367,7 +473,7 @@ // will have a hard time tracking down an unnammed structure type in // the module DWO file, so we make sure we don't get into this // situation by always resolving typedefs from the DWO file. - const DWARFDIE encoding_die = encoding_uid.Reference(); + const DWARFDIE encoding_die = attrs.type.Reference(); // First make sure that the die that this is typedef'ed to _is_ just // a declaration (DW_AT_declaration == 1), not a full definition @@ -391,8 +497,7 @@ break; case DW_TAG_unspecified_type: - if (strcmp(type_name_cstr, "nullptr_t") == 0 || - strcmp(type_name_cstr, "decltype(nullptr)") == 0) { + if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") { resolve_state = Type::eResolveStateFull; clang_type = m_ast.GetBasicType(eBasicTypeNullPtr); break; @@ -404,7 +509,8 @@ case DW_TAG_base_type: resolve_state = Type::eResolveStateFull; clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( - type_name_cstr, encoding, byte_size.getValueOr(0) * 8); + attrs.name.GetCString(), attrs.encoding, + attrs.byte_size.getValueOr(0) * 8); break; case DW_TAG_pointer_type: @@ -458,7 +564,7 @@ clang_type = m_ast.CreateBlockPointerType( lldb_function_type_sp->GetForwardCompilerType()); encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); + attrs.type.Clear(); resolve_state = Type::eResolveStateFull; } } @@ -471,12 +577,12 @@ if (cu_language == eLanguageTypeObjC || cu_language == eLanguageTypeObjC_plus_plus) { - if (type_name_cstr != nullptr) { + if (attrs.name) { static ConstString g_objc_type_name_id("id"); static ConstString g_objc_type_name_Class("Class"); static ConstString g_objc_type_name_selector("SEL"); - if (type_name_const_str == g_objc_type_name_id) { + if (attrs.name == g_objc_type_name_id) { if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( log, @@ -485,10 +591,10 @@ die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCID); encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); + attrs.type.Clear(); resolve_state = Type::eResolveStateFull; - } else if (type_name_const_str == g_objc_type_name_Class) { + } else if (attrs.name == g_objc_type_name_Class) { if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( log, @@ -497,9 +603,9 @@ die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); + attrs.type.Clear(); resolve_state = Type::eResolveStateFull; - } else if (type_name_const_str == g_objc_type_name_selector) { + } else if (attrs.name == g_objc_type_name_selector) { if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( log, @@ -508,15 +614,15 @@ die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); + attrs.type.Clear(); resolve_state = Type::eResolveStateFull; } } else if (encoding_data_type == Type::eEncodingIsPointerUID && - encoding_uid.IsValid()) { + attrs.type.IsValid()) { // Clang sometimes erroneously emits id as objc_object*. In that // case we fix up the type to "id". - const DWARFDIE encoding_die = encoding_uid.Reference(); + const DWARFDIE encoding_die = attrs.type.Reference(); if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) { if (const char *struct_name = encoding_die.GetName()) { @@ -530,7 +636,7 @@ die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCID); encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); + attrs.type.Clear(); resolve_state = Type::eResolveStateFull; } } @@ -540,8 +646,8 @@ } type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, - dwarf->GetUID(DIERef(encoding_uid)), encoding_data_type, &decl, + die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, + dwarf->GetUID(DIERef(attrs.type)), encoding_data_type, &attrs.decl, clang_type, resolve_state); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); @@ -550,72 +656,6 @@ case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: { - LanguageType class_language = eLanguageTypeUnknown; - bool is_complete_objc_class = false; - size_t calling_convention = llvm::dwarf::CallingConvention::DW_CC_normal; - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - - case DW_AT_APPLE_runtime_class: - class_language = (LanguageType)form_value.Signed(); - break; - - case DW_AT_APPLE_objc_complete_type: - is_complete_objc_class = form_value.Signed(); - break; - case DW_AT_calling_convention: - calling_convention = form_value.Unsigned(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - default: - case DW_AT_sibling: - break; - } - } - } - } - // UniqueDWARFASTType is large, so don't create a local variables on // the stack, put it on the heap. This function is often called // recursively and clang isn't good and sharing the stack space for @@ -623,10 +663,10 @@ std::unique_ptr unique_ast_entry_up( new UniqueDWARFASTType()); - ConstString unique_typename(type_name_const_str); - Declaration unique_decl(decl); + ConstString unique_typename(attrs.name); + Declaration unique_decl(attrs.decl); - if (type_name_const_str) { + if (attrs.name) { if (Language::LanguageIsCPlusPlus(cu_language)) { // For C++, we rely solely upon the one definition rule that says // only one thing can exist at a given decl context. We ignore the @@ -638,7 +678,7 @@ } if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, byte_size ? *byte_size : -1, + unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), *unique_ast_entry_up)) { type_sp = unique_ast_entry_up->m_type_sp; if (type_sp) { @@ -664,8 +704,8 @@ default_accessibility = eAccessPrivate; } - if (byte_size && *byte_size == 0 && type_name_cstr && !die.HasChildren() && - cu_language == eLanguageTypeObjC) { + if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && cu_language == eLanguageTypeObjC) { // Work around an issue with clang at the moment where forward // declarations for objective C classes are emitted as: // DW_TAG_structure_type [2] @@ -676,20 +716,20 @@ // // Note that there is no DW_AT_declaration and there are no children, // and the byte size is zero. - is_forward_declaration = true; + attrs.is_forward_declaration = true; } - if (class_language == eLanguageTypeObjC || - class_language == eLanguageTypeObjC_plus_plus) { - if (!is_complete_objc_class && + if (attrs.class_language == eLanguageTypeObjC || + attrs.class_language == eLanguageTypeObjC_plus_plus) { + if (!attrs.is_complete_objc_class && die.Supports_DW_AT_APPLE_objc_complete_type()) { // We have a valid eSymbolTypeObjCClass class symbol whose name // matches the current objective C class that we are trying to find // and this DIE isn't the complete definition (we checked // is_complete_objc_class above and know it is false), so the real // definition is in here somewhere - type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE( - die, type_name_const_str, true); + type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); if (!type_sp) { SymbolFileDWARFDebugMap *debug_map_symfile = @@ -698,7 +738,7 @@ // We weren't able to find a full declaration in this DWARF, // see if we have a declaration anywhere else... type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( - die, type_name_const_str, true); + die, attrs.name, true); } } @@ -709,7 +749,8 @@ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " "incomplete objc type, complete type is 0x%8.8" PRIx64, static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); } // We found a real definition for this type elsewhere so lets use @@ -721,7 +762,7 @@ } } - if (is_forward_declaration) { + if (attrs.is_forward_declaration) { // We have a forward declaration to a type and we need to try and // find a full declaration. We look in the current type index just in // case we have a forward declaration followed by an actual @@ -733,7 +774,7 @@ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " "forward declaration, trying to find complete type", static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr); + DW_TAG_value_to_name(tag), attrs.name.GetCString()); } // See if the type comes from a DWO module and if so, track down that @@ -767,7 +808,8 @@ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " "forward declaration, complete type is 0x%8.8" PRIx64, static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); } // We found a real definition for this type elsewhere so lets use @@ -794,27 +836,27 @@ // not an issue in the non-gmodules case because the debug info will // always contain a full definition of parent types in that case. CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, - type_name_cstr); + attrs.name.GetCString()); - if (accessibility == eAccessNone && decl_ctx) { + if (attrs.accessibility == eAccessNone && decl_ctx) { // Check the decl context that contains this class/struct/union. If // it is a class we must give it an accessibility. const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); if (DeclKindIsCXXClass(containing_decl_kind)) - accessibility = default_accessibility; + attrs.accessibility = default_accessibility; } ClangASTMetadata metadata; metadata.SetUserID(die.GetID()); metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - if (type_name_cstr && strchr(type_name_cstr, '<')) { + if (attrs.name.GetStringRef().contains('<')) { ClangASTContext::TemplateParameterInfos template_param_infos; if (ParseTemplateParameterInfos(die, template_param_infos)) { clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, accessibility, - type_name_cstr, tag_decl_kind, - template_param_infos); + m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, + attrs.name.GetCString(), + tag_decl_kind, template_param_infos); if (!class_template_decl) { if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( @@ -822,7 +864,7 @@ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " "clang::ClassTemplateDecl failed to return a decl.", static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr); + DW_TAG_value_to_name(tag), attrs.name.GetCString()); } return TypeSP(); } @@ -842,9 +884,9 @@ if (!clang_type_was_created) { clang_type_was_created = true; - clang_type = - m_ast.CreateRecordType(decl_ctx, accessibility, type_name_cstr, - tag_decl_kind, class_language, &metadata); + clang_type = m_ast.CreateRecordType( + decl_ctx, attrs.accessibility, attrs.name.GetCString(), + tag_decl_kind, attrs.class_language, &metadata); } } @@ -852,12 +894,12 @@ // parameters in any class methods need it for the clang types for // function prototypes. LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp = std::make_shared(die.GetID(), dwarf, type_name_const_str, - byte_size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, &decl, clang_type, + type_sp = std::make_shared(die.GetID(), dwarf, attrs.name, + attrs.byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, clang_type, Type::eResolveStateForward); - type_sp->SetIsCompleteObjCClass(is_complete_objc_class); + type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); // Add our type to the unique type map so we don't end up creating many // copies of the same type over and over in the ASTContext for our @@ -865,11 +907,11 @@ unique_ast_entry_up->m_type_sp = type_sp; unique_ast_entry_up->m_die = die; unique_ast_entry_up->m_declaration = unique_decl; - unique_ast_entry_up->m_byte_size = byte_size.getValueOr(0); + unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, *unique_ast_entry_up); - if (is_forward_declaration && die.HasChildren()) { + if (attrs.is_forward_declaration && die.HasChildren()) { // Check to see if the DIE actually has a definition, some version of // GCC will // emit DIEs with DW_AT_declaration set to true, but yet still have @@ -887,7 +929,7 @@ case DW_TAG_typedef: case DW_TAG_union_type: child_die.Clear(); - is_forward_declaration = false; + attrs.is_forward_declaration = false; break; default: child_die = child_die.GetSibling(); @@ -896,7 +938,7 @@ } } - if (!is_forward_declaration) { + if (!attrs.is_forward_declaration) { // Always start the definition for a class type so that if the class // has child classes or types that require the class to be created // for use as their decl contexts the class will be ready to accept @@ -910,7 +952,7 @@ "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " "definition.\nPlease file a bug and attach the file at the " "start of this error message", - die.GetOffset(), type_name_cstr); + die.GetOffset(), attrs.name.GetCString()); } if (tag == DW_TAG_structure_type) // this only applies in C @@ -932,8 +974,8 @@ // class is needed as the declaration context for a contained class // or type without the need to complete that type.. - if (class_language != eLanguageTypeObjC && - class_language != eLanguageTypeObjC_plus_plus) + if (attrs.class_language != eLanguageTypeObjC && + attrs.class_language != eLanguageTypeObjC_plus_plus) ClangASTContext::StartTagDeclarationDefinition(clang_type); // Leave this as a forward declaration until we need to know the @@ -961,7 +1003,7 @@ // do this for pass by value - which implies the Trivial ABI. There // isn't a way to assert that something that would normally be pass by // value is pass by reference, so we ignore that attribute if set. - if (calling_convention == llvm::dwarf::DW_CC_pass_by_value) { + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); if (record_decl) { @@ -969,7 +1011,7 @@ } } - if (calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); if (record_decl) @@ -980,281 +1022,119 @@ } break; case DW_TAG_enumeration_type: { - bool is_scoped = false; - DWARFFormValue encoding_form; + if (attrs.is_forward_declaration) { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_type: - encoding_form = form_value; - break; - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - case DW_AT_accessibility: - break; // accessibility = - // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - case DW_AT_enum_class: - is_scoped = form_value.Boolean(); - break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_bit_stride: - case DW_AT_byte_stride: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); } } - if (is_forward_declaration) { - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); } - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); - } + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = - GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; - } + CompilerType enumerator_clang_type; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + if (attrs.type.IsValid()) { + Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(attrs.type)); + if (enumerator_type) + enumerator_clang_type = enumerator_type->GetFullCompilerType(); } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - CompilerType enumerator_clang_type; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - if (encoding_form.IsValid()) { - Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form)); - if (enumerator_type) - enumerator_clang_type = enumerator_type->GetFullCompilerType(); - } - - if (!enumerator_clang_type) { - if (byte_size) { - enumerator_clang_type = - m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( - NULL, DW_ATE_signed, *byte_size * 8); - } else { - enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); - } + if (!enumerator_clang_type) { + if (attrs.byte_size) { + enumerator_clang_type = + m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( + NULL, DW_ATE_signed, *attrs.byte_size * 8); + } else { + enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); } - - clang_type = m_ast.CreateEnumerationType( - type_name_cstr, GetClangDeclContextContainingDIE(die, nullptr), - decl, enumerator_clang_type, is_scoped); - } else { - enumerator_clang_type = - m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); } - LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), - die); + clang_type = m_ast.CreateEnumerationType( + attrs.name.GetCString(), + GetClangDeclContextContainingDIE(die, nullptr), attrs.decl, + enumerator_clang_type, attrs.is_scoped_enum); + } else { + enumerator_clang_type = + m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); + } + + LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), + die); - type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, - dwarf->GetUID(DIERef(encoding_form)), Type::eEncodingIsUID, &decl, - clang_type, Type::eResolveStateForward); - - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - if (die.HasChildren()) { - SymbolContext cu_sc(die.GetLLDBCompileUnit()); - bool is_signed = false; - enumerator_clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(cu_sc, clang_type, is_signed, - type_sp->GetByteSize().getValueOr(0), die); - } - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), type_name_cstr); + type_sp = std::make_shared( + die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, + dwarf->GetUID(DIERef(attrs.type)), Type::eEncodingIsUID, &attrs.decl, + clang_type, Type::eResolveStateForward); + + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + if (die.HasChildren()) { + SymbolContext cu_sc(die.GetLLDBCompileUnit()); + bool is_signed = false; + enumerator_clang_type.IsIntegerType(is_signed); + ParseChildEnumerators(cu_sc, clang_type, is_signed, + type_sp->GetByteSize().getValueOr(0), die); } + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), attrs.name.GetCString()); } } break; case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: case DW_TAG_subroutine_type: { - DWARFFormValue type_die_form; bool is_variadic = false; - bool is_inline = false; bool is_static = false; - bool is_virtual = false; - bool is_explicit = false; - bool is_artificial = false; bool has_template_params = false; - DWARFFormValue specification_die_form; - DWARFFormValue abstract_origin_die_form; - DWARFDIE object_pointer_die; unsigned type_quals = 0; - clang::StorageClass storage = - clang::SC_None; //, Extern, Static, PrivateExtern - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_linkage_name: - case DW_AT_MIPS_linkage_name: - mangled_name_cstr = form_value.AsCString(); - break; - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - case DW_AT_declaration: - break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_inline: - is_inline = form_value.Boolean(); - break; - case DW_AT_virtuality: - is_virtual = form_value.Boolean(); - break; - case DW_AT_explicit: - is_explicit = form_value.Boolean(); - break; - case DW_AT_artificial: - is_artificial = form_value.Boolean(); - break; - - case DW_AT_external: - if (form_value.Unsigned()) { - if (storage == clang::SC_None) - storage = clang::SC_Extern; - else - storage = clang::SC_PrivateExtern; - } - break; - - case DW_AT_specification: - specification_die_form = form_value; - break; - - case DW_AT_abstract_origin: - abstract_origin_die_form = form_value; - break; - - case DW_AT_object_pointer: - object_pointer_die = form_value.Reference(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_address_class: - case DW_AT_calling_convention: - case DW_AT_data_location: - case DW_AT_elemental: - case DW_AT_entry_pc: - case DW_AT_frame_base: - case DW_AT_high_pc: - case DW_AT_low_pc: - case DW_AT_prototyped: - case DW_AT_pure: - case DW_AT_ranges: - case DW_AT_recursive: - case DW_AT_return_addr: - case DW_AT_segment: - case DW_AT_start_scope: - case DW_AT_static_link: - case DW_AT_trampoline: - case DW_AT_visibility: - case DW_AT_vtable_elem_location: - case DW_AT_description: - case DW_AT_sibling: - break; - } - } - } - } std::string object_pointer_name; - if (object_pointer_die) { - const char *object_pointer_name_cstr = object_pointer_die.GetName(); + if (attrs.object_pointer) { + const char *object_pointer_name_cstr = attrs.object_pointer.GetName(); if (object_pointer_name_cstr) object_pointer_name = object_pointer_name_cstr; } @@ -1265,8 +1145,8 @@ CompilerType return_clang_type; Type *func_type = NULL; - if (type_die_form.IsValid()) - func_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); + if (attrs.type.IsValid()) + func_type = dwarf->ResolveTypeUID(DIERef(attrs.type)); if (func_type) return_clang_type = func_type->GetForwardCompilerType(); @@ -1322,10 +1202,10 @@ return_clang_type, function_param_types.data(), function_param_types.size(), is_variadic, type_quals); - if (type_name_cstr) { + if (attrs.name) { bool type_handled = false; if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { - ObjCLanguage::MethodName objc_method(type_name_cstr, true); + ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true); if (objc_method.IsValid(true)) { CompilerType class_opaque_type; ConstString class_name(objc_method.GetClassName()); @@ -1346,13 +1226,13 @@ if (class_opaque_type) { // If accessibility isn't set to anything valid, assume public // for now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; + if (attrs.accessibility == eAccessNone) + attrs.accessibility = eAccessPublic; clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType( - class_opaque_type, type_name_cstr, clang_type, - accessibility, is_artificial, is_variadic); + class_opaque_type, attrs.name.GetCString(), clang_type, + attrs.accessibility, attrs.is_artificial, is_variadic); type_handled = objc_method_decl != NULL; if (type_handled) { LinkDeclContextToDIE( @@ -1401,7 +1281,7 @@ } } - if (specification_die_form.IsValid()) { + if (attrs.specification.IsValid()) { // We have a specification which we are going to base our // function prototype off of, so we need this type to be // completed so that the m_die_to_decl_ctx for the method in @@ -1411,7 +1291,7 @@ // have been made with the specification and not with this // die. DWARFDIE spec_die = - dwarf->DebugInfo()->GetDIE(DIERef(specification_die_form)); + dwarf->DebugInfo()->GetDIE(DIERef(attrs.specification)); clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE(spec_die); if (spec_clang_decl_ctx) { @@ -1420,11 +1300,10 @@ dwarf->GetObjectFile()->GetModule()->ReportWarning( "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x" ") has no decl\n", - die.GetID(), - specification_die_form.Reference().GetOffset()); + die.GetID(), attrs.specification.Reference().GetOffset()); } type_handled = true; - } else if (abstract_origin_die_form.IsValid()) { + } else if (attrs.abstract_origin.IsValid()) { // We have a specification which we are going to base our // function prototype off of, so we need this type to be // completed so that the m_die_to_decl_ctx for the method in @@ -1432,7 +1311,7 @@ class_type->GetForwardCompilerType(); DWARFDIE abs_die = - dwarf->DebugInfo()->GetDIE(DIERef(abstract_origin_die_form)); + dwarf->DebugInfo()->GetDIE(DIERef(attrs.abstract_origin)); clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE(abs_die); if (abs_clang_decl_ctx) { @@ -1441,8 +1320,7 @@ dwarf->GetObjectFile()->GetModule()->ReportWarning( "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x" ") has no decl\n", - die.GetID(), - abstract_origin_die_form.Reference().GetOffset()); + die.GetID(), attrs.abstract_origin.Reference().GetOffset()); } type_handled = true; } else { @@ -1471,7 +1349,7 @@ method_iter++) { clang::CXXMethodDecl *method_decl = *method_iter; if (method_decl->getNameInfo().getAsString() == - std::string(type_name_cstr)) { + attrs.name.GetStringRef()) { if (method_decl->getType() == ClangUtil::GetQualType(clang_type)) { add_method = false; @@ -1492,8 +1370,8 @@ llvm::PrettyStackTraceFormat stack_trace( "SymbolFileDWARF::ParseType() is adding a method " "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", - type_name_cstr, class_type->GetName().GetCString(), - die.GetID(), + attrs.name.GetCString(), + class_type->GetName().GetCString(), die.GetID(), dwarf->GetObjectFile() ->GetFileSpec() .GetPath() @@ -1503,15 +1381,16 @@ // Neither GCC 4.2 nor clang++ currently set a valid // accessibility in the DWARF for C++ methods... // Default to public for now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; + if (attrs.accessibility == eAccessNone) + attrs.accessibility = eAccessPublic; clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), - type_name_cstr, mangled_name_cstr, clang_type, - accessibility, is_virtual, is_static, is_inline, - is_explicit, is_attr_used, is_artificial); + attrs.name.GetCString(), attrs.mangled_name, + clang_type, attrs.accessibility, attrs.is_virtual, + is_static, attrs.is_inline, attrs.is_explicit, + is_attr_used, attrs.is_artificial); type_handled = cxx_method_decl != NULL; @@ -1582,8 +1461,8 @@ clang::FunctionDecl *function_decl = nullptr; clang::FunctionDecl *template_function_decl = nullptr; - if (abstract_origin_die_form.IsValid()) { - DWARFDIE abs_die = abstract_origin_die_form.Reference(); + if (attrs.abstract_origin.IsValid()) { + DWARFDIE abs_die = attrs.abstract_origin.Reference(); SymbolContext sc; @@ -1602,7 +1481,8 @@ function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - type_name_cstr, clang_type, storage, is_inline); + attrs.name.GetCString(), clang_type, attrs.storage, + attrs.is_inline); if (has_template_params) { ClangASTContext::TemplateParameterInfos template_param_infos; @@ -1610,11 +1490,12 @@ template_function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - type_name_cstr, clang_type, storage, is_inline); + attrs.name.GetCString(), clang_type, attrs.storage, + attrs.is_inline); clang::FunctionTemplateDecl *func_template_decl = m_ast.CreateFunctionTemplateDecl( - containing_decl_ctx, template_function_decl, type_name_cstr, - template_param_infos); + containing_decl_ctx, template_function_decl, + attrs.name.GetCString(), template_param_infos); m_ast.CreateFunctionTemplateSpecializationInfo( function_decl, func_template_decl, template_param_infos); } @@ -1650,203 +1531,115 @@ } } } - type_sp = std::make_shared(die.GetID(), dwarf, type_name_const_str, - llvm::None, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, &decl, clang_type, - Type::eResolveStateFull); + type_sp = std::make_shared( + die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, clang_type, Type::eResolveStateFull); assert(type_sp.get()); } break; case DW_TAG_array_type: { - DWARFFormValue type_die_form; - uint32_t byte_stride = 0; - uint32_t bit_stride = 0; - bool is_vector = false; - const size_t num_attributes = die.GetAttributes(attributes); + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; + DIERef type_die_ref(attrs.type); + Type *element_type = dwarf->ResolveTypeUID(type_die_ref); - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_byte_size: - break; // byte_size = form_value.Unsigned(); break; - case DW_AT_byte_stride: - byte_stride = form_value.Unsigned(); - break; - case DW_AT_bit_stride: - bit_stride = form_value.Unsigned(); - break; - case DW_AT_GNU_vector: - is_vector = form_value.Boolean(); - break; - case DW_AT_accessibility: - break; // accessibility = - // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: - break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_ordering: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } + if (element_type) { + auto array_info = ParseChildArrayInfo(die); + if (array_info) { + attrs.byte_stride = array_info->byte_stride; + attrs.bit_stride = array_info->bit_stride; + } + if (attrs.byte_stride == 0 && attrs.bit_stride == 0) + attrs.byte_stride = element_type->GetByteSize().getValueOr(0); + CompilerType array_element_type = element_type->GetForwardCompilerType(); + + if (ClangASTContext::IsCXXClassType(array_element_type) && + !array_element_type.GetCompleteType()) { + ModuleSP module_sp = die.GetModule(); + if (module_sp) { + if (die.GetCU()->GetProducer() == eProducerClang) + module_sp->ReportError( + "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " + "class/union/struct element type DIE 0x%8.8x that is a " + "forward declaration, not a complete definition.\nTry " + "compiling the source file with -fstandalone-debug or " + "disable -gmodules", + die.GetOffset(), type_die_ref.die_offset); + else + module_sp->ReportError( + "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " + "class/union/struct element type DIE 0x%8.8x that is a " + "forward declaration, not a complete definition.\nPlease " + "file a bug against the compiler and include the " + "preprocessed output for %s", + die.GetOffset(), type_die_ref.die_offset, + die.GetLLDBCompileUnit() + ? die.GetLLDBCompileUnit()->GetPath().c_str() + : "the source file"); + } + + // We have no choice other than to pretend that the element class + // type is complete. If we don't do this, clang will crash when + // trying to layout the class. Since we provide layout + // assistance, all ivars in this class and other classes will be + // fine, this is the best we can do short of crashing. + if (ClangASTContext::StartTagDeclarationDefinition( + array_element_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(array_element_type); + } else { + module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to " + "start its definition.\nPlease file a " + "bug and attach the file at the start " + "of this error message", + type_die_ref.die_offset); } } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - DIERef type_die_ref(type_die_form); - Type *element_type = dwarf->ResolveTypeUID(type_die_ref); - - if (element_type) { - auto array_info = ParseChildArrayInfo(die); - if (array_info) { - byte_stride = array_info->byte_stride; - bit_stride = array_info->bit_stride; - } - if (byte_stride == 0 && bit_stride == 0) - byte_stride = element_type->GetByteSize().getValueOr(0); - CompilerType array_element_type = - element_type->GetForwardCompilerType(); - - if (ClangASTContext::IsCXXClassType(array_element_type) && - !array_element_type.GetCompleteType()) { - ModuleSP module_sp = die.GetModule(); - if (module_sp) { - if (die.GetCU()->GetProducer() == eProducerClang) - module_sp->ReportError( - "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " - "class/union/struct element type DIE 0x%8.8x that is a " - "forward declaration, not a complete definition.\nTry " - "compiling the source file with -fstandalone-debug or " - "disable -gmodules", - die.GetOffset(), type_die_ref.die_offset); - else - module_sp->ReportError( - "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " - "class/union/struct element type DIE 0x%8.8x that is a " - "forward declaration, not a complete definition.\nPlease " - "file a bug against the compiler and include the " - "preprocessed output for %s", - die.GetOffset(), type_die_ref.die_offset, - die.GetLLDBCompileUnit() - ? die.GetLLDBCompileUnit()->GetPath().c_str() - : "the source file"); - } - - // We have no choice other than to pretend that the element class - // type is complete. If we don't do this, clang will crash when - // trying to layout the class. Since we provide layout - // assistance, all ivars in this class and other classes will be - // fine, this is the best we can do short of crashing. - if (ClangASTContext::StartTagDeclarationDefinition( - array_element_type)) { - ClangASTContext::CompleteTagDeclarationDefinition( - array_element_type); - } else { - module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to " - "start its definition.\nPlease file a " - "bug and attach the file at the start " - "of this error message", - type_die_ref.die_offset); - } - } - - uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; - if (array_info && array_info->element_orders.size() > 0) { - uint64_t num_elements = 0; - auto end = array_info->element_orders.rend(); - for (auto pos = array_info->element_orders.rbegin(); pos != end; - ++pos) { - num_elements = *pos; - clang_type = m_ast.CreateArrayType(array_element_type, num_elements, - is_vector); - array_element_type = clang_type; - array_element_bit_stride = - num_elements ? array_element_bit_stride * num_elements - : array_element_bit_stride; - } - } else { - clang_type = m_ast.CreateArrayType(array_element_type, 0, is_vector); + uint64_t array_element_bit_stride = + attrs.byte_stride * 8 + attrs.bit_stride; + if (array_info && array_info->element_orders.size() > 0) { + uint64_t num_elements = 0; + auto end = array_info->element_orders.rend(); + for (auto pos = array_info->element_orders.rbegin(); pos != end; + ++pos) { + num_elements = *pos; + clang_type = m_ast.CreateArrayType(array_element_type, num_elements, + attrs.is_vector); + array_element_type = clang_type; + array_element_bit_stride = + num_elements ? array_element_bit_stride * num_elements + : array_element_bit_stride; } - ConstString empty_name; - type_sp = std::make_shared( - die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, - nullptr, dwarf->GetUID(DIERef(type_die_form)), Type::eEncodingIsUID, - &decl, clang_type, Type::eResolveStateFull); - type_sp->SetEncodingType(element_type); - m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID()); + } else { + clang_type = m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector); } + ConstString empty_name; + type_sp = std::make_shared( + die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr, + dwarf->GetUID(type_die_ref), Type::eEncodingIsUID, &attrs.decl, + clang_type, Type::eResolveStateFull); + type_sp->SetEncodingType(element_type); + m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID()); } } break; case DW_TAG_ptr_to_member_type: { - DWARFFormValue type_die_form; - DWARFFormValue containing_type_die_form; + Type *pointee_type = dwarf->ResolveTypeUID(DIERef(attrs.type)); + Type *class_type = dwarf->ResolveTypeUID(DIERef(attrs.containing_type)); - const size_t num_attributes = die.GetAttributes(attributes); + CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType(); + CompilerType class_clang_type = class_type->GetLayoutCompilerType(); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_containing_type: - containing_type_die_form = form_value; - break; - } - } - } + clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, + pointee_clang_type); - Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); - Type *class_type = - dwarf->ResolveTypeUID(DIERef(containing_type_die_form)); - - CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType(); - CompilerType class_clang_type = class_type->GetLayoutCompilerType(); - - clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, - pointee_clang_type); - - if (llvm::Optional clang_type_size = - clang_type.GetByteSize(nullptr)) { - byte_size = *clang_type_size; - type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type, - Type::eResolveStateForward); - } + if (llvm::Optional clang_type_size = + clang_type.GetByteSize(nullptr)) { + type_sp = std::make_shared( + die.GetID(), dwarf, attrs.name, *clang_type_size, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type, + Type::eResolveStateForward); } break;