1 //===-- DWARFDeclContext.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 "DWARFDeclContext.h" 10 #include "llvm/Support/raw_ostream.h" 11 12 using namespace lldb_private::dwarf; 13 using namespace lldb_private::plugin::dwarf; 14 GetName() const15const char *DWARFDeclContext::Entry::GetName() const { 16 if (name != nullptr) 17 return name; 18 if (tag == DW_TAG_namespace) 19 return "(anonymous namespace)"; 20 if (tag == DW_TAG_class_type) 21 return "(anonymous class)"; 22 if (tag == DW_TAG_structure_type) 23 return "(anonymous struct)"; 24 if (tag == DW_TAG_union_type) 25 return "(anonymous union)"; 26 return "(anonymous)"; 27 } 28 GetQualifiedName() const29const char *DWARFDeclContext::GetQualifiedName() const { 30 if (m_qualified_name.empty()) { 31 // The declaration context array for a class named "foo" in namespace 32 // "a::b::c" will be something like: 33 // [0] DW_TAG_class_type "foo" 34 // [1] DW_TAG_namespace "c" 35 // [2] DW_TAG_namespace "b" 36 // [3] DW_TAG_namespace "a" 37 if (!m_entries.empty()) { 38 if (m_entries.size() == 1) { 39 if (m_entries[0].name) { 40 m_qualified_name.append("::"); 41 m_qualified_name.append(m_entries[0].name); 42 } 43 } else { 44 llvm::raw_string_ostream string_stream(m_qualified_name); 45 llvm::interleave( 46 llvm::reverse(m_entries), string_stream, 47 [&](auto entry) { string_stream << entry.GetName(); }, "::"); 48 } 49 } 50 } 51 if (m_qualified_name.empty()) 52 return nullptr; 53 return m_qualified_name.c_str(); 54 } 55 operator ==(const DWARFDeclContext & rhs) const56bool DWARFDeclContext::operator==(const DWARFDeclContext &rhs) const { 57 if (m_entries.size() != rhs.m_entries.size()) 58 return false; 59 60 collection::const_iterator pos; 61 collection::const_iterator begin = m_entries.begin(); 62 collection::const_iterator end = m_entries.end(); 63 64 collection::const_iterator rhs_pos; 65 collection::const_iterator rhs_begin = rhs.m_entries.begin(); 66 // The two entry arrays have the same size 67 68 // First compare the tags before we do expensive name compares 69 for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos) { 70 if (pos->tag != rhs_pos->tag) { 71 // Check for DW_TAG_structure_type and DW_TAG_class_type as they are 72 // often used interchangeably in GCC 73 if (pos->tag == DW_TAG_structure_type && 74 rhs_pos->tag == DW_TAG_class_type) 75 continue; 76 if (pos->tag == DW_TAG_class_type && 77 rhs_pos->tag == DW_TAG_structure_type) 78 continue; 79 return false; 80 } 81 } 82 // The tags all match, now compare the names 83 for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos) { 84 if (!pos->NameMatches(*rhs_pos)) 85 return false; 86 } 87 // All tags and names match 88 return true; 89 } 90