Fixed an issue where we might accept the wrong type when completing

a type when we have a forward declaration. We always have found a 
type by basename, but now we also compare the decl context of the 
die we are trying to complete with the matches we find from the accelerator
tables to ensure we get the right one.

llvm-svn: 149593
This commit is contained in:
Greg Clayton 2012-02-02 05:48:16 +00:00
parent 3a20bc3652
commit 890ff5615a
4 changed files with 89 additions and 12 deletions

View File

@ -1726,6 +1726,18 @@ DWARFDebugInfoEntry::BuildFunctionAddressRangeTable
}
}
void
DWARFDebugInfoEntry::GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
DWARFDIECollection &decl_context_dies) const
{
const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
if (parent_decl_ctx_die && parent_decl_ctx_die != this)
{
decl_context_dies.Append(parent_decl_ctx_die);
parent_decl_ctx_die->GetDeclContextDIEs (dwarf2Data, cu, decl_context_dies);
}
}
const DWARFDebugInfoEntry *
DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,

View File

@ -355,6 +355,10 @@ public:
const DWARFDebugInfoEntry* GetFirstChild() const { return (HasChildren() && !m_empty_children) ? this + 1 : NULL; }
void GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
DWARFDIECollection &decl_context_dies) const;
const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu) const;
const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,

View File

@ -4045,6 +4045,60 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
return type_sp;
}
bool
SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2)
{
assert (die1 != die2);
DWARFDIECollection decl_ctx_1;
DWARFDIECollection decl_ctx_2;
die1->GetDeclContextDIEs (this, cu1, decl_ctx_1);
die1->GetDeclContextDIEs (this, cu2, decl_ctx_2);
const size_t count1 = decl_ctx_1.Size();
const size_t count2 = decl_ctx_2.Size();
if (count1 != count2)
return false;
const DWARFDebugInfoEntry *decl_ctx_die1;
const DWARFDebugInfoEntry *decl_ctx_die2;
size_t i;
for (i=0; i<count1; i++)
{
decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
if (decl_ctx_die1->Tag() != decl_ctx_die2->Tag())
return false;
}
// Make sure the top item in the decl context die array is always a compile unit
#if defined LLDB_CONFIGURATION_DEBUG
assert (decl_ctx_1.GetDIEPtrAtIndex (count1 - 1)->Tag() == DW_TAG_compile_unit);
#endif
// Always skip the compile unit when comparing by only iterating up to
// "count1 - 1"
for (i=0; i<count1 - 1; i++)
{
decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
const char *name1 = decl_ctx_die1->GetName(this, cu1);
const char *name2 = decl_ctx_die1->GetName(this, cu2);
// If the string was from a DW_FORM_strp, then the pointer will often
// be the same!
if (name1 != name2)
{
if (name1 && name2)
{
// If the strings don't compare, we are done...
if (strcmp(name1, name2) != 0)
return false;
}
else
{
// One name was NULL while the other wasn't
return false;
}
}
}
return true;
}
// This function can be used when a DIE is found that is a forward declaration
// DIE and we want to try and find a type that has the complete definition.
@ -4136,19 +4190,23 @@ SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu,
if (try_resolving_type)
{
Type *resolved_type = ResolveType (type_cu, type_die, false);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
// Make sure the decl contexts match all the way up
if (DIEDeclContextsMatch(cu, die, type_cu, type_die))
{
DEBUG_PRINTF ("resolved 0x%8.8llx (cu 0x%8.8llx) from %s to 0x%8.8llx (cu 0x%8.8llx)\n",
MakeUserID(die->GetOffset()),
MakeUserID(curr_cu->GetOffset()),
m_obj_file->GetFileSpec().GetFilename().AsCString(),
MakeUserID(type_die->GetOffset()),
MakeUserID(type_cu->GetOffset()));
m_die_to_type[die] = resolved_type;
type_sp = resolved_type->shared_from_this();
break;
Type *resolved_type = ResolveType (type_cu, type_die, false);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
{
DEBUG_PRINTF ("resolved 0x%8.8llx (cu 0x%8.8llx) from %s to 0x%8.8llx (cu 0x%8.8llx)\n",
MakeUserID(die->GetOffset()),
MakeUserID(curr_cu->GetOffset()),
m_obj_file->GetFileSpec().GetFilename().AsCString(),
MakeUserID(type_die->GetOffset()),
MakeUserID(type_cu->GetOffset()));
m_die_to_type[die] = resolved_type;
type_sp = resolved_type;
break;
}
}
}
}

View File

@ -503,6 +503,9 @@ protected:
int tag_decl_kind,
const lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
bool
DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2);
SymbolFileDWARFDebugMap * m_debug_map_symfile;
clang::TranslationUnitDecl * m_clang_tu_decl;