xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
11 #include "lldb/Core/Declaration.h"
12 
13 using namespace lldb_private::dwarf;
14 using namespace lldb_private::plugin::dwarf;
15 
IsStructOrClassTag(llvm::dwarf::Tag Tag)16 static bool IsStructOrClassTag(llvm::dwarf::Tag Tag) {
17   return Tag == llvm::dwarf::Tag::DW_TAG_class_type ||
18          Tag == llvm::dwarf::Tag::DW_TAG_structure_type;
19 }
20 
Find(const DWARFDIE & die,const lldb_private::Declaration & decl,const int32_t byte_size,bool is_forward_declaration)21 UniqueDWARFASTType *UniqueDWARFASTTypeList::Find(
22     const DWARFDIE &die, const lldb_private::Declaration &decl,
23     const int32_t byte_size, bool is_forward_declaration) {
24   for (UniqueDWARFASTType &udt : m_collection) {
25     // Make sure the tags match
26     if (udt.m_die.Tag() == die.Tag() || (IsStructOrClassTag(udt.m_die.Tag()) &&
27                                          IsStructOrClassTag(die.Tag()))) {
28       // If they are not both definition DIEs or both declaration DIEs, then
29       // don't check for byte size and declaration location, because declaration
30       // DIEs usually don't have those info.
31       bool matching_size_declaration =
32           udt.m_is_forward_declaration != is_forward_declaration
33               ? true
34               : (udt.m_byte_size < 0 || byte_size < 0 ||
35                  udt.m_byte_size == byte_size) &&
36                     udt.m_declaration == decl;
37       if (!matching_size_declaration)
38         continue;
39       // The type has the same name, and was defined on the same file and
40       // line. Now verify all of the parent DIEs match.
41       DWARFDIE parent_arg_die = die.GetParent();
42       DWARFDIE parent_pos_die = udt.m_die.GetParent();
43       bool match = true;
44       bool done = false;
45       while (!done && match && parent_arg_die && parent_pos_die) {
46         const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
47         const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
48         if (parent_arg_tag == parent_pos_tag ||
49             (IsStructOrClassTag(parent_arg_tag) &&
50              IsStructOrClassTag(parent_pos_tag))) {
51           switch (parent_arg_tag) {
52           case DW_TAG_class_type:
53           case DW_TAG_structure_type:
54           case DW_TAG_union_type:
55           case DW_TAG_namespace: {
56             const char *parent_arg_die_name = parent_arg_die.GetName();
57             if (parent_arg_die_name == nullptr) {
58               // Anonymous (i.e. no-name) struct
59               match = false;
60             } else {
61               const char *parent_pos_die_name = parent_pos_die.GetName();
62               if (parent_pos_die_name == nullptr ||
63                   ((parent_arg_die_name != parent_pos_die_name) &&
64                    strcmp(parent_arg_die_name, parent_pos_die_name)))
65                 match = false;
66             }
67           } break;
68 
69           case DW_TAG_compile_unit:
70           case DW_TAG_partial_unit:
71             done = true;
72             break;
73           default:
74             break;
75           }
76         }
77         parent_arg_die = parent_arg_die.GetParent();
78         parent_pos_die = parent_pos_die.GetParent();
79       }
80 
81       if (match) {
82         return &udt;
83       }
84     }
85   }
86   return nullptr;
87 }
88