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
13using namespace lldb_private::dwarf;
14
15bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
16                                  const lldb_private::Declaration &decl,
17                                  const int32_t byte_size,
18                                  UniqueDWARFASTType &entry) const {
19  for (const UniqueDWARFASTType &udt : m_collection) {
20    // Make sure the tags match
21    if (udt.m_die.Tag() == die.Tag()) {
22      // Validate byte sizes of both types only if both are valid.
23      if (udt.m_byte_size < 0 || byte_size < 0 ||
24          udt.m_byte_size == byte_size) {
25        // Make sure the file and line match
26        if (udt.m_declaration == decl) {
27          // The type has the same name, and was defined on the same file and
28          // line. Now verify all of the parent DIEs match.
29          DWARFDIE parent_arg_die = die.GetParent();
30          DWARFDIE parent_pos_die = udt.m_die.GetParent();
31          bool match = true;
32          bool done = false;
33          while (!done && match && parent_arg_die && parent_pos_die) {
34            const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
35            const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
36            if (parent_arg_tag == parent_pos_tag) {
37              switch (parent_arg_tag) {
38              case DW_TAG_class_type:
39              case DW_TAG_structure_type:
40              case DW_TAG_union_type:
41              case DW_TAG_namespace: {
42                const char *parent_arg_die_name = parent_arg_die.GetName();
43                if (parent_arg_die_name ==
44                    nullptr) // Anonymous (i.e. no-name) struct
45                {
46                  match = false;
47                } else {
48                  const char *parent_pos_die_name = parent_pos_die.GetName();
49                  if (parent_pos_die_name == nullptr ||
50                      ((parent_arg_die_name != parent_pos_die_name) &&
51                       strcmp(parent_arg_die_name, parent_pos_die_name)))
52                    match = false;
53                }
54              } break;
55
56              case DW_TAG_compile_unit:
57              case DW_TAG_partial_unit:
58                done = true;
59                break;
60              default:
61                break;
62              }
63            }
64            parent_arg_die = parent_arg_die.GetParent();
65            parent_pos_die = parent_pos_die.GetParent();
66          }
67
68          if (match) {
69            entry = udt;
70            return true;
71          }
72        }
73      }
74    }
75  }
76  return false;
77}
78