1 //===-- UniqueDWARFASTType.cpp --------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "UniqueDWARFASTType.h" 10 #include "SymbolFileDWARF.h" 11 12 #include "lldb/Core/Declaration.h" 13 #include "lldb/Target/Language.h" 14 15 using namespace lldb_private::dwarf; 16 using namespace lldb_private::plugin::dwarf; 17 18 static bool IsStructOrClassTag(llvm::dwarf::Tag Tag) { 19 return Tag == llvm::dwarf::Tag::DW_TAG_class_type || 20 Tag == llvm::dwarf::Tag::DW_TAG_structure_type; 21 } 22 23 static bool IsSizeAndDeclarationMatching(UniqueDWARFASTType const &udt, 24 DWARFDIE const &die, 25 const lldb_private::Declaration &decl, 26 const int32_t byte_size, 27 bool is_forward_declaration) { 28 29 // If they are not both definition DIEs or both declaration DIEs, then 30 // don't check for byte size and declaration location, because declaration 31 // DIEs usually don't have those info. 32 if (udt.m_is_forward_declaration != is_forward_declaration) 33 return true; 34 35 if (udt.m_byte_size > 0 && byte_size > 0 && udt.m_byte_size != byte_size) 36 return false; 37 38 // For C++, we match the behaviour of 39 // DWARFASTParserClang::GetUniqueTypeNameAndDeclaration. We rely on the 40 // one-definition-rule: for a given fully qualified name there exists only one 41 // definition, and there should only be one entry for such name, so ignore 42 // location of where it was declared vs. defined. 43 if (lldb_private::Language::LanguageIsCPlusPlus( 44 SymbolFileDWARF::GetLanguage(*die.GetCU()))) 45 return true; 46 47 return udt.m_declaration == decl; 48 } 49 50 UniqueDWARFASTType *UniqueDWARFASTTypeList::Find( 51 const DWARFDIE &die, const lldb_private::Declaration &decl, 52 const int32_t byte_size, bool is_forward_declaration) { 53 for (UniqueDWARFASTType &udt : m_collection) { 54 // Make sure the tags match 55 if (udt.m_die.Tag() == die.Tag() || (IsStructOrClassTag(udt.m_die.Tag()) && 56 IsStructOrClassTag(die.Tag()))) { 57 58 if (!IsSizeAndDeclarationMatching(udt, die, decl, byte_size, 59 is_forward_declaration)) 60 continue; 61 62 // The type has the same name, and was defined on the same file and 63 // line. Now verify all of the parent DIEs match. 64 DWARFDIE parent_arg_die = die.GetParent(); 65 DWARFDIE parent_pos_die = udt.m_die.GetParent(); 66 bool match = true; 67 bool done = false; 68 while (!done && match && parent_arg_die && parent_pos_die) { 69 const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); 70 const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); 71 if (parent_arg_tag == parent_pos_tag || 72 (IsStructOrClassTag(parent_arg_tag) && 73 IsStructOrClassTag(parent_pos_tag))) { 74 switch (parent_arg_tag) { 75 case DW_TAG_class_type: 76 case DW_TAG_structure_type: 77 case DW_TAG_union_type: 78 case DW_TAG_namespace: { 79 const char *parent_arg_die_name = parent_arg_die.GetName(); 80 if (parent_arg_die_name == nullptr) { 81 // Anonymous (i.e. no-name) struct 82 match = false; 83 } else { 84 const char *parent_pos_die_name = parent_pos_die.GetName(); 85 if (parent_pos_die_name == nullptr || 86 ((parent_arg_die_name != parent_pos_die_name) && 87 strcmp(parent_arg_die_name, parent_pos_die_name))) 88 match = false; 89 } 90 } break; 91 92 case DW_TAG_compile_unit: 93 case DW_TAG_partial_unit: 94 done = true; 95 break; 96 default: 97 break; 98 } 99 } 100 parent_arg_die = parent_arg_die.GetParent(); 101 parent_pos_die = parent_pos_die.GetParent(); 102 } 103 104 if (match) { 105 return &udt; 106 } 107 } 108 } 109 return nullptr; 110 } 111