1254721Semaste//===-- DWARFDeclContext.cpp ------------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "DWARFDeclContext.h"
10254721Semaste
11314564Sdimconst char *DWARFDeclContext::GetQualifiedName() const {
12314564Sdim  if (m_qualified_name.empty()) {
13314564Sdim    // The declaration context array for a class named "foo" in namespace
14314564Sdim    // "a::b::c" will be something like:
15314564Sdim    //  [0] DW_TAG_class_type "foo"
16314564Sdim    //  [1] DW_TAG_namespace "c"
17314564Sdim    //  [2] DW_TAG_namespace "b"
18314564Sdim    //  [3] DW_TAG_namespace "a"
19314564Sdim    if (!m_entries.empty()) {
20314564Sdim      if (m_entries.size() == 1) {
21314564Sdim        if (m_entries[0].name) {
22314564Sdim          m_qualified_name.append("::");
23314564Sdim          m_qualified_name.append(m_entries[0].name);
24314564Sdim        }
25314564Sdim      } else {
26314564Sdim        collection::const_reverse_iterator pos;
27314564Sdim        collection::const_reverse_iterator begin = m_entries.rbegin();
28314564Sdim        collection::const_reverse_iterator end = m_entries.rend();
29314564Sdim        for (pos = begin; pos != end; ++pos) {
30314564Sdim          if (pos != begin)
31314564Sdim            m_qualified_name.append("::");
32353358Sdim          if (pos->name == nullptr) {
33314564Sdim            if (pos->tag == DW_TAG_namespace)
34314564Sdim              m_qualified_name.append("(anonymous namespace)");
35314564Sdim            else if (pos->tag == DW_TAG_class_type)
36314564Sdim              m_qualified_name.append("(anonymous class)");
37314564Sdim            else if (pos->tag == DW_TAG_structure_type)
38314564Sdim              m_qualified_name.append("(anonymous struct)");
39314564Sdim            else if (pos->tag == DW_TAG_union_type)
40314564Sdim              m_qualified_name.append("(anonymous union)");
41254721Semaste            else
42314564Sdim              m_qualified_name.append("(anonymous)");
43314564Sdim          } else
44314564Sdim            m_qualified_name.append(pos->name);
45254721Semaste        }
46314564Sdim      }
47254721Semaste    }
48314564Sdim  }
49314564Sdim  if (m_qualified_name.empty())
50353358Sdim    return nullptr;
51314564Sdim  return m_qualified_name.c_str();
52254721Semaste}
53254721Semaste
54314564Sdimbool DWARFDeclContext::operator==(const DWARFDeclContext &rhs) const {
55314564Sdim  if (m_entries.size() != rhs.m_entries.size())
56314564Sdim    return false;
57254721Semaste
58314564Sdim  collection::const_iterator pos;
59314564Sdim  collection::const_iterator begin = m_entries.begin();
60314564Sdim  collection::const_iterator end = m_entries.end();
61254721Semaste
62314564Sdim  collection::const_iterator rhs_pos;
63314564Sdim  collection::const_iterator rhs_begin = rhs.m_entries.begin();
64314564Sdim  // The two entry arrays have the same size
65314564Sdim
66314564Sdim  // First compare the tags before we do expensive name compares
67314564Sdim  for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos) {
68314564Sdim    if (pos->tag != rhs_pos->tag) {
69341825Sdim      // Check for DW_TAG_structure_type and DW_TAG_class_type as they are
70341825Sdim      // often used interchangeably in GCC
71314564Sdim      if (pos->tag == DW_TAG_structure_type &&
72314564Sdim          rhs_pos->tag == DW_TAG_class_type)
73314564Sdim        continue;
74314564Sdim      if (pos->tag == DW_TAG_class_type &&
75314564Sdim          rhs_pos->tag == DW_TAG_structure_type)
76314564Sdim        continue;
77314564Sdim      return false;
78254721Semaste    }
79314564Sdim  }
80314564Sdim  // The tags all match, now compare the names
81314564Sdim  for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos) {
82314564Sdim    if (!pos->NameMatches(*rhs_pos))
83314564Sdim      return false;
84314564Sdim  }
85314564Sdim  // All tags and names match
86314564Sdim  return true;
87254721Semaste}
88