Files
clang-p2996/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
Greg Clayton 109f86860a Fix issues with GCC debugging. GCC emits DWARF in unique ways that LLDB wasn't handling. This fix will fix cases where classes are forward declared using DW_TAG_structure_type and then actually defined using DW_TAG_class_type. LLDB, when it finds a forward declaration, would try and find and parse the complete type. It does this by:
1 - looking up the type basename in the type index
2 - iterate through all matches and look for decl contexts (namespace/class hierarchy) that match

The issue was the decl context matching wasn't watching for DW_TAG_class_type/DW_TAG_structure_type mismatches, and it wasn't also getting the name for DIE's that didn't have a DW_AT_name, but did have a DW_AT_specification that had a name.

llvm-svn: 186347
2013-07-15 21:10:17 +00:00

105 lines
3.6 KiB
C++

//===-- DWARFDeclContext.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DWARFDeclContext.h"
const char *
DWARFDeclContext::GetQualifiedName () const
{
if (m_qualified_name.empty())
{
// The declaration context array for a class named "foo" in namespace
// "a::b::c" will be something like:
// [0] DW_TAG_class_type "foo"
// [1] DW_TAG_namespace "c"
// [2] DW_TAG_namespace "b"
// [3] DW_TAG_namespace "a"
if (!m_entries.empty())
{
if (m_entries.size() == 1)
{
if (m_entries[0].name)
{
m_qualified_name.append("::");
m_qualified_name.append(m_entries[0].name);
}
}
else
{
collection::const_reverse_iterator pos;
collection::const_reverse_iterator begin = m_entries.rbegin();
collection::const_reverse_iterator end = m_entries.rend();
for (pos = begin; pos != end; ++pos)
{
if (pos != begin)
m_qualified_name.append("::");
if (pos->name == NULL)
{
if (pos->tag == DW_TAG_namespace)
m_qualified_name.append ("(anonymous namespace)");
else if (pos->tag == DW_TAG_class_type)
m_qualified_name.append ("(anonymous class)");
else if (pos->tag == DW_TAG_structure_type)
m_qualified_name.append ("(anonymous struct)");
else if (pos->tag == DW_TAG_union_type)
m_qualified_name.append ("(anonymous union)");
else
m_qualified_name.append ("(anonymous)");
}
else
m_qualified_name.append(pos->name);
}
}
}
}
if (m_qualified_name.empty())
return NULL;
return m_qualified_name.c_str();
}
bool
DWARFDeclContext::operator==(const DWARFDeclContext& rhs) const
{
if (m_entries.size() != rhs.m_entries.size())
return false;
collection::const_iterator pos;
collection::const_iterator begin = m_entries.begin();
collection::const_iterator end = m_entries.end();
collection::const_iterator rhs_pos;
collection::const_iterator rhs_begin = rhs.m_entries.begin();
// The two entry arrays have the same size
// First compare the tags before we do expensize name compares
for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos)
{
if (pos->tag != rhs_pos->tag)
{
// Check for DW_TAG_structure_type and DW_TAG_class_type as they are often
// used interchangeably in GCC
if (pos->tag == DW_TAG_structure_type && rhs_pos->tag == DW_TAG_class_type)
continue;
if (pos->tag == DW_TAG_class_type && rhs_pos->tag == DW_TAG_structure_type)
continue;
return false;
}
}
// The tags all match, now compare the names
for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos)
{
if (!pos->NameMatches (*rhs_pos))
return false;
}
// All tags and names match
return true;
}