Revert "[lldb][DebugNames] Only skip processing of DW_AT_declarations for class/union types"

and two follow-up commits. The reason is the crash we've discovered when
processing -gsimple-template-names binaries. I'm committing a minimal
reproducer as a separate patch.

This reverts the following commits:
- 51dd4eaaa2 (#92328)
- 3d9d485239 (#93839)
- afe6ab7586 (#94400)
This commit is contained in:
Pavel Labath
2024-06-06 15:06:46 +00:00
parent 67aaa9f997
commit 7fdbc30b44
12 changed files with 410 additions and 498 deletions

View File

@@ -60,8 +60,6 @@ public:
virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0;
virtual lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) = 0;
static std::optional<SymbolFile::ArrayInfo>
ParseChildArrayInfo(const DWARFDIE &parent_die,
const ExecutionContext *exe_ctx = nullptr);

View File

@@ -154,26 +154,6 @@ static bool TagIsRecordType(dw_tag_t tag) {
}
}
static bool IsForwardDeclaration(const DWARFDIE &die,
const ParsedDWARFTypeAttributes &attrs,
LanguageType cu_language) {
if (attrs.is_forward_declaration)
return true;
// Work around an issue with clang at the moment where forward
// declarations for objective C classes are emitted as:
// DW_TAG_structure_type [2]
// DW_AT_name( "ForwardObjcClass" )
// DW_AT_byte_size( 0x00 )
// DW_AT_decl_file( "..." )
// DW_AT_decl_line( 1 )
//
// Note that there is no DW_AT_declaration and there are no children,
// and the byte size is zero.
return attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
!die.HasChildren() && cu_language == eLanguageTypeObjC;
}
TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
const DWARFDIE &die,
Log *log) {
@@ -269,9 +249,11 @@ static void ForcefullyCompleteType(CompilerType type) {
/// This function serves a similar purpose as RequireCompleteType above, but it
/// avoids completing the type if it is not immediately necessary. It only
/// ensures we _can_ complete the type later.
void DWARFASTParserClang::PrepareContextToReceiveMembers(
clang::DeclContext *decl_ctx, const DWARFDIE &decl_ctx_die,
const DWARFDIE &die, const char *type_name_cstr) {
static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
ClangASTImporter &ast_importer,
clang::DeclContext *decl_ctx,
DWARFDIE die,
const char *type_name_cstr) {
auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
if (!tag_decl_ctx)
return; // Non-tag context are always ready.
@@ -286,8 +268,7 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers(
// gmodules case), we can complete the type by doing a full import.
// If this type was not imported from an external AST, there's nothing to do.
CompilerType type = m_ast.GetTypeForDecl(tag_decl_ctx);
ClangASTImporter &ast_importer = GetClangASTImporter();
CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
if (type && ast_importer.CanImport(type)) {
auto qual_type = ClangUtil::GetQualType(type);
if (ast_importer.RequireCompleteType(qual_type))
@@ -298,13 +279,6 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers(
type_name_cstr ? type_name_cstr : "", die.GetOffset());
}
// By searching for the definition DIE of the decl_ctx type, we will either:
// 1. Found the the definition DIE and start its definition with
// TypeSystemClang::StartTagDeclarationDefinition.
// 2. Unable to find it, then need to forcefully complete it.
FindDefinitionTypeForDIE(decl_ctx_die);
if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
return;
// We don't have a type definition and/or the import failed. We must
// forcefully complete the type to avoid crashes.
ForcefullyCompleteType(type);
@@ -650,11 +624,10 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
if (tag == DW_TAG_typedef) {
// DeclContext will be populated when the clang type is materialized in
// Type::ResolveCompilerType.
DWARFDIE decl_ctx_die;
clang::DeclContext *decl_ctx =
GetClangDeclContextContainingDIE(die, &decl_ctx_die);
PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die,
attrs.name.GetCString());
PrepareContextToReceiveMembers(
m_ast, GetClangASTImporter(),
GetClangDeclContextContainingDIE(die, nullptr), die,
attrs.name.GetCString());
if (attrs.type.IsValid()) {
// Try to parse a typedef from the (DWARF embedded in the) Clang
@@ -1134,6 +1107,32 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
// struct and see if this is actually a C++ method
Type *class_type = dwarf->ResolveType(decl_ctx_die);
if (class_type) {
if (class_type->GetID() != decl_ctx_die.GetID() ||
IsClangModuleFwdDecl(decl_ctx_die)) {
// We uniqued the parent class of this function to another
// class so we now need to associate all dies under
// "decl_ctx_die" to DIEs in the DIE for "class_type"...
DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
if (class_type_die) {
std::vector<DWARFDIE> failures;
CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
class_type, failures);
// FIXME do something with these failures that's
// smarter than just dropping them on the ground.
// Unfortunately classes don't like having stuff added
// to them after their definitions are complete...
Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
return type_ptr->shared_from_this();
}
}
}
if (attrs.specification.IsValid()) {
// We have a specification which we are going to base our
// function prototype off of, so we need this type to be
@@ -1268,39 +1267,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
}
}
}
// By here, we should have already completed the c++ class_type
// because if either specification or abstract_origin is present, we
// call GetClangDeclContextForDIE to resolve the DW_TAG_subprogram
// refered by this one until we reached the DW_TAG_subprogram without
// specification or abstract_origin (the else branch above). Then the
// above GetFullCompilerType() will complete the class_type if it's
// not completed yet. After that, we will have the mapping from DIEs
// in class_type_die to DeclContexts in m_die_to_decl_ctx.
if (class_type->GetID() != decl_ctx_die.GetID() ||
IsClangModuleFwdDecl(decl_ctx_die)) {
// We uniqued the parent class of this function to another
// class so we now need to associate all dies under
// "decl_ctx_die" to DIEs in the DIE for "class_type"...
DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
if (class_type_die) {
std::vector<DWARFDIE> failures;
CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
class_type, failures);
// FIXME do something with these failures that's
// smarter than just dropping them on the ground.
// Unfortunately classes don't like having stuff added
// to them after their definitions are complete...
Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
return type_ptr->shared_from_this();
}
}
}
}
}
}
@@ -1673,29 +1639,81 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
return qualified_name;
}
lldb_private::Type *
DWARFASTParserClang::FindDefinitionTypeForDIE(const DWARFDIE &die) {
SymbolFileDWARF *dwarf = die.GetDWARF();
ParsedDWARFTypeAttributes attrs(die);
bool is_forward_declaration = IsForwardDeclaration(
die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU()));
if (!is_forward_declaration)
return dwarf->GetDIEToType()[die.GetDIE()];
const dw_tag_t tag = die.Tag();
TypeSP
DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs) {
TypeSP type_sp;
CompilerType clang_type;
const dw_tag_t tag = die.Tag();
SymbolFileDWARF *dwarf = die.GetDWARF();
LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());
Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
if (log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
"SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
"forward declaration DIE, trying to find definition DIE",
static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
attrs.name.GetCString());
// UniqueDWARFASTType is large, so don't create a local variables on the
// stack, put it on the heap. This function is often called recursively and
// clang isn't good at sharing the stack space for variables in different
// blocks.
auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>();
ConstString unique_typename(attrs.name);
Declaration unique_decl(attrs.decl);
if (attrs.name) {
if (Language::LanguageIsCPlusPlus(cu_language)) {
// For C++, we rely solely upon the one definition rule that says
// only one thing can exist at a given decl context. We ignore the
// file and line that things are declared on.
std::string qualified_name = GetCPlusPlusQualifiedName(die);
if (!qualified_name.empty())
unique_typename = ConstString(qualified_name);
unique_decl.Clear();
}
if (dwarf->GetUniqueDWARFASTTypeMap().Find(
unique_typename, die, unique_decl, attrs.byte_size.value_or(-1),
*unique_ast_entry_up)) {
type_sp = unique_ast_entry_up->m_type_sp;
if (type_sp) {
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
LinkDeclContextToDIE(
GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die);
return type_sp;
}
}
}
// We haven't parse definition die for this type, starting to search for it.
// After we found the definition die, the GetDeclarationDIEToDefinitionDIE()
// map will have the new mapping from this declaration die to definition die.
DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
DW_TAG_value_to_name(tag), type_name_cstr);
int tag_decl_kind = -1;
AccessType default_accessibility = eAccessNone;
if (tag == DW_TAG_structure_type) {
tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Struct);
default_accessibility = eAccessPublic;
} else if (tag == DW_TAG_union_type) {
tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Union);
default_accessibility = eAccessPublic;
} else if (tag == DW_TAG_class_type) {
tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Class);
default_accessibility = eAccessPrivate;
}
if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
!die.HasChildren() && cu_language == eLanguageTypeObjC) {
// Work around an issue with clang at the moment where forward
// declarations for objective C classes are emitted as:
// DW_TAG_structure_type [2]
// DW_AT_name( "ForwardObjcClass" )
// DW_AT_byte_size( 0x00 )
// DW_AT_decl_file( "..." )
// DW_AT_decl_line( 1 )
//
// Note that there is no DW_AT_declaration and there are no children,
// and the byte size is zero.
attrs.is_forward_declaration = true;
}
if (attrs.class_language == eLanguageTypeObjC ||
attrs.class_language == eLanguageTypeObjC_plus_plus) {
if (!attrs.is_complete_objc_class &&
@@ -1719,146 +1737,87 @@ DWARFASTParserClang::FindDefinitionTypeForDIE(const DWARFDIE &die) {
}
}
if (type_sp && log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
"SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is an "
"incomplete objc type, complete type is {5:x8}",
static_cast<void *>(this), die.GetOffset(),
DW_TAG_value_to_name(tag), tag, attrs.name.GetCString(),
type_sp->GetID());
}
}
}
type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
if (!type_sp) {
SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
// We weren't able to find a full declaration in this DWARF, see
// if we have a declaration anywhere else...
type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
}
if (type_sp && log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
"SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
"forward declaration, complete type is {4:x8}",
static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
attrs.name.GetCString(), type_sp->GetID());
}
}
if (!type_sp && log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
"SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
"forward declaration, unable to find definition DIE for it",
static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
attrs.name.GetCString());
}
return type_sp.get();
}
TypeSP
DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs) {
TypeSP type_sp;
CompilerType clang_type;
const dw_tag_t tag = die.Tag();
SymbolFileDWARF *dwarf = die.GetDWARF();
LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());
Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
ConstString unique_typename(attrs.name);
Declaration unique_decl(attrs.decl);
uint64_t byte_size = attrs.byte_size.value_or(0);
attrs.is_forward_declaration = IsForwardDeclaration(die, attrs, cu_language);
if (attrs.name) {
if (Language::LanguageIsCPlusPlus(cu_language)) {
// For C++, we rely solely upon the one definition rule that says
// only one thing can exist at a given decl context. We ignore the
// file and line that things are declared on.
std::string qualified_name = GetCPlusPlusQualifiedName(die);
if (!qualified_name.empty())
unique_typename = ConstString(qualified_name);
unique_decl.Clear();
}
if (UniqueDWARFASTType *unique_ast_entry_type =
dwarf->GetUniqueDWARFASTTypeMap().Find(
unique_typename, die, unique_decl, byte_size,
attrs.is_forward_declaration)) {
type_sp = unique_ast_entry_type->m_type_sp;
if (type_sp) {
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
LinkDeclContextToDIE(
GetCachedClangDeclContextForDIE(unique_ast_entry_type->m_die), die);
if (!attrs.is_forward_declaration) {
// If the DIE being parsed in this function is a definition and the
// entry in the map is a declaration, then we need to update the entry
// to point to the definition DIE.
if (unique_ast_entry_type->m_is_forward_declaration) {
unique_ast_entry_type->m_die = die;
unique_ast_entry_type->m_byte_size = byte_size;
unique_ast_entry_type->m_declaration = unique_decl;
unique_ast_entry_type->m_is_forward_declaration = false;
// Need to update Type ID to refer to the definition DIE. because
// it's used in ParseSubroutine to determine if we need to copy cxx
// method types from a declaration DIE to this definition DIE.
type_sp->SetID(die.GetID());
clang_type = type_sp->GetForwardCompilerType();
if (attrs.class_language != eLanguageTypeObjC &&
attrs.class_language != eLanguageTypeObjC_plus_plus)
TypeSystemClang::StartTagDeclarationDefinition(clang_type);
CompilerType compiler_type_no_qualifiers =
ClangUtil::RemoveFastQualifiers(clang_type);
auto result = dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
compiler_type_no_qualifiers.GetOpaqueQualType(),
*die.GetDIERef());
if (!result.second)
result.first->second = *die.GetDIERef();
}
if (log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
"SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is an "
"incomplete objc type, complete type is {5:x8}",
static_cast<void *>(this), die.GetOffset(),
DW_TAG_value_to_name(tag), tag, attrs.name.GetCString(),
type_sp->GetID());
}
// We found a real definition for this type elsewhere so lets use
// it and cache the fact that we found a complete type for this
// die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
return type_sp;
}
}
}
DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
DW_TAG_value_to_name(tag), type_name_cstr);
int tag_decl_kind = -1;
AccessType default_accessibility = eAccessNone;
if (tag == DW_TAG_structure_type) {
tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Struct);
default_accessibility = eAccessPublic;
} else if (tag == DW_TAG_union_type) {
tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Union);
default_accessibility = eAccessPublic;
} else if (tag == DW_TAG_class_type) {
tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Class);
default_accessibility = eAccessPrivate;
}
if (attrs.is_forward_declaration) {
// We have a forward declaration to a type and we need to try and
// find a full declaration. We look in the current type index just in
// case we have a forward declaration followed by an actual
// declarations in the DWARF. If this fails, we need to look
// elsewhere...
if (log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
"SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is a "
"forward declaration, trying to find complete type",
static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
tag, attrs.name.GetCString());
}
// See if the type comes from a Clang module and if so, track down
// that type.
type_sp = ParseTypeFromClangModule(sc, die, log);
if (type_sp)
return type_sp;
}
// type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
// type_name_const_str);
type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
if (!type_sp) {
SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
// We weren't able to find a full declaration in this DWARF, see
// if we have a declaration anywhere else...
type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
}
}
if (type_sp) {
if (log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
"SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is a "
"forward declaration, complete type is {5:x8}",
static_cast<void *>(this), die.GetOffset(),
DW_TAG_value_to_name(tag), tag, attrs.name.GetCString(),
type_sp->GetID());
}
// We found a real definition for this type elsewhere so lets use
// it and cache the fact that we found a complete type for this die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
clang::DeclContext *defn_decl_ctx =
GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
if (defn_decl_ctx)
LinkDeclContextToDIE(defn_decl_ctx, die);
return type_sp;
}
}
assert(tag_decl_kind != -1);
UNUSED_IF_ASSERT_DISABLED(tag_decl_kind);
DWARFDIE decl_ctx_die;
clang::DeclContext *decl_ctx =
GetClangDeclContextContainingDIE(die, &decl_ctx_die);
bool clang_type_was_created = false;
clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr);
PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die,
PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die,
attrs.name.GetCString());
if (attrs.accessibility == eAccessNone && decl_ctx) {
@@ -1897,17 +1856,20 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
tag_decl_kind, template_param_infos);
clang_type =
m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
clang_type_was_created = true;
m_ast.SetMetadata(class_template_decl, metadata);
m_ast.SetMetadata(class_specialization_decl, metadata);
}
if (!clang_type) {
if (!clang_type_was_created) {
clang_type_was_created = true;
clang_type = m_ast.CreateRecordType(
decl_ctx, GetOwningClangModule(die), attrs.accessibility,
attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata,
attrs.exports_symbols);
}
// Store a forward declaration to this class type in case any
// parameters in any class methods need it for the clang types for
// function prototypes.
@@ -1918,19 +1880,13 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
Type::ResolveState::Forward,
TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class));
// UniqueDWARFASTType is large, so don't create a local variables on the
// stack, put it on the heap. This function is often called recursively and
// clang isn't good at sharing the stack space for variables in different
// blocks.
auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>();
// Add our type to the unique type map so we don't end up creating many
// copies of the same type over and over in the ASTContext for our
// module
unique_ast_entry_up->m_type_sp = type_sp;
unique_ast_entry_up->m_die = die;
unique_ast_entry_up->m_declaration = unique_decl;
unique_ast_entry_up->m_byte_size = byte_size;
unique_ast_entry_up->m_is_forward_declaration = attrs.is_forward_declaration;
unique_ast_entry_up->m_byte_size = attrs.byte_size.value_or(0);
dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
*unique_ast_entry_up);
@@ -1971,7 +1927,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
GetClangASTImporter().SetRecordLayout(record_decl, layout);
}
}
} else {
} else if (clang_type_was_created) {
// Start the definition if the class is not objective C since the
// underlying decls respond to isCompleteDefinition(). Objective
// C decls don't respond to isCompleteDefinition() so we can't
@@ -1983,21 +1939,26 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
if (attrs.class_language != eLanguageTypeObjC &&
attrs.class_language != eLanguageTypeObjC_plus_plus)
TypeSystemClang::StartTagDeclarationDefinition(clang_type);
// Leave this as a forward declaration until we need to know the
// details of the type. lldb_private::Type will automatically call
// the SymbolFile virtual function
// "SymbolFileDWARF::CompleteType(Type *)" When the definition
// needs to be defined.
assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count(
ClangUtil::RemoveFastQualifiers(clang_type)
.GetOpaqueQualType()) &&
"Type already in the forward declaration map!");
// Can't assume m_ast.GetSymbolFile() is actually a
// SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple
// binaries.
dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),
*die.GetDIERef());
m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
}
}
// If this is a declaration DIE, leave this as a forward declaration until we
// need to know the details of the type. lldb_private::Type will automatically
// call the SymbolFile virtual function "SymbolFileDWARF::CompleteType(Type
// *)" When the definition needs to be defined.
assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count(
ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) &&
"Type already in the forward declaration map!");
dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),
*die.GetDIERef());
m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
// If we made a clang type, set the trivial abi if applicable: We only
// do this for pass by value - which implies the Trivial ABI. There
// isn't a way to assert that something that would normally be pass by
@@ -2236,10 +2197,6 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
// For objective C we don't start the definition when the class is
// created.
TypeSystemClang::StartTagDeclarationDefinition(clang_type);
} else {
assert(clang_type.IsBeingDefined() &&
"Trying to complete a definition without a prior call to "
"StartTagDeclarationDefinition.");
}
AccessType default_accessibility = eAccessNone;

View File

@@ -42,40 +42,40 @@ struct ParsedDWARFTypeAttributes;
class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
public:
typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE;
DWARFASTParserClang(lldb_private::TypeSystemClang &ast);
~DWARFASTParserClang() override;
// DWARFASTParser interface.
lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
const DWARFDIE &die,
bool *type_is_new_ptr) override;
lldb::TypeSP
ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
const lldb_private::plugin::dwarf::DWARFDIE &die,
bool *type_is_new_ptr) override;
lldb_private::ConstString
ConstructDemangledNameFromDWARF(const DWARFDIE &die) override;
lldb_private::ConstString ConstructDemangledNameFromDWARF(
const lldb_private::plugin::dwarf::DWARFDIE &die) override;
lldb_private::Function *
ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
const DWARFDIE &die,
const lldb_private::plugin::dwarf::DWARFDIE &die,
const lldb_private::AddressRange &func_range) override;
bool
CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
CompleteTypeFromDWARF(const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb_private::Type *type,
lldb_private::CompilerType &compiler_type) override;
lldb_private::CompilerDecl
GetDeclForUIDFromDWARF(const DWARFDIE &die) override;
lldb_private::CompilerDecl GetDeclForUIDFromDWARF(
const lldb_private::plugin::dwarf::DWARFDIE &die) override;
void EnsureAllDIEsInDeclContextHaveBeenParsed(
lldb_private::CompilerDeclContext decl_context) override;
lldb_private::CompilerDeclContext
GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override;
lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(
const lldb_private::plugin::dwarf::DWARFDIE &die) override;
lldb_private::CompilerDeclContext
GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override;
lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(
const lldb_private::plugin::dwarf::DWARFDIE &die) override;
lldb_private::ClangASTImporter &GetClangASTImporter();
@@ -105,13 +105,8 @@ public:
/// \return A string, including surrounding '<>', of the template parameters.
/// If the DIE's name already has '<>', returns an empty ConstString because
/// it's assumed that the caller is using the DIE name anyway.
lldb_private::ConstString
GetDIEClassTemplateParams(const DWARFDIE &die) override;
// Searching for definition DIE for the given DIE and return the type
// associated with the definition DIE, or nullptr if definition DIE is not
// found.
lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) override;
lldb_private::ConstString GetDIEClassTemplateParams(
const lldb_private::plugin::dwarf::DWARFDIE &die) override;
protected:
/// Protected typedefs and members.
@@ -123,7 +118,8 @@ protected:
const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *,
clang::DeclContext *>
DIEToDeclContextMap;
typedef std::multimap<const clang::DeclContext *, const DWARFDIE>
typedef std::multimap<const clang::DeclContext *,
const lldb_private::plugin::dwarf::DWARFDIE>
DeclContextToDIEMap;
typedef llvm::DenseMap<
const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *,
@@ -141,11 +137,14 @@ protected:
std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up;
/// @}
clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die);
clang::DeclContext *
GetDeclContextForBlock(const lldb_private::plugin::dwarf::DWARFDIE &die);
clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die);
clang::BlockDecl *
ResolveBlockDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die);
clang::NamespaceDecl *
ResolveNamespaceDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
/// Returns the namespace decl that a DW_TAG_imported_declaration imports.
///
@@ -156,86 +155,96 @@ protected:
/// 'die' imports. If the imported entity is not a namespace
/// or another import declaration, returns nullptr. If an error
/// occurs, returns nullptr.
clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die);
clang::NamespaceDecl *ResolveImportedDeclarationDIE(
const lldb_private::plugin::dwarf::DWARFDIE &die);
bool ParseTemplateDIE(const DWARFDIE &die,
bool ParseTemplateDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb_private::TypeSystemClang::TemplateParameterInfos
&template_param_infos);
bool ParseTemplateParameterInfos(
const DWARFDIE &parent_die,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
lldb_private::TypeSystemClang::TemplateParameterInfos
&template_param_infos);
std::string GetCPlusPlusQualifiedName(const DWARFDIE &die);
std::string
GetCPlusPlusQualifiedName(const lldb_private::plugin::dwarf::DWARFDIE &die);
bool ParseChildMembers(
const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type,
const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb_private::CompilerType &class_compiler_type,
std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
std::vector<DWARFDIE> &member_function_dies,
std::vector<DWARFDIE> &contained_type_dies,
std::vector<lldb_private::plugin::dwarf::DWARFDIE> &member_function_dies,
std::vector<lldb_private::plugin::dwarf::DWARFDIE> &contained_type_dies,
DelayedPropertyList &delayed_properties,
const lldb::AccessType default_accessibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
size_t
ParseChildParameters(clang::DeclContext *containing_decl_ctx,
const DWARFDIE &parent_die, bool skip_artificial,
bool &is_static, bool &is_variadic,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
bool skip_artificial, bool &is_static, bool &is_variadic,
bool &has_template_params,
std::vector<lldb_private::CompilerType> &function_args,
std::vector<clang::ParmVarDecl *> &function_param_decls,
unsigned &type_quals);
size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type,
bool is_signed, uint32_t enumerator_byte_size,
const DWARFDIE &parent_die);
size_t ParseChildEnumerators(
lldb_private::CompilerType &compiler_type, bool is_signed,
uint32_t enumerator_byte_size,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die);
/// Parse a structure, class, or union type DIE.
lldb::TypeSP ParseStructureLikeDIE(const lldb_private::SymbolContext &sc,
const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP
ParseStructureLikeDIE(const lldb_private::SymbolContext &sc,
const lldb_private::plugin::dwarf::DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs);
clang::Decl *GetClangDeclForDIE(const DWARFDIE &die);
clang::Decl *
GetClangDeclForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
clang::DeclContext *GetClangDeclContextForDIE(const DWARFDIE &die);
clang::DeclContext *
GetClangDeclContextForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die,
DWARFDIE *decl_ctx_die);
lldb_private::OptionalClangModuleID GetOwningClangModule(const DWARFDIE &die);
clang::DeclContext *GetClangDeclContextContainingDIE(
const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb_private::plugin::dwarf::DWARFDIE *decl_ctx_die);
lldb_private::OptionalClangModuleID
GetOwningClangModule(const lldb_private::plugin::dwarf::DWARFDIE &die);
bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die,
const DWARFDIE &dst_class_die,
lldb_private::Type *class_type,
std::vector<DWARFDIE> &failures);
bool CopyUniqueClassMethodTypes(
const lldb_private::plugin::dwarf::DWARFDIE &src_class_die,
const lldb_private::plugin::dwarf::DWARFDIE &dst_class_die,
lldb_private::Type *class_type,
std::vector<lldb_private::plugin::dwarf::DWARFDIE> &failures);
clang::DeclContext *GetCachedClangDeclContextForDIE(const DWARFDIE &die);
clang::DeclContext *GetCachedClangDeclContextForDIE(
const lldb_private::plugin::dwarf::DWARFDIE &die);
void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, const DWARFDIE &die);
void LinkDeclContextToDIE(clang::DeclContext *decl_ctx,
const lldb_private::plugin::dwarf::DWARFDIE &die);
void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die);
void LinkDeclToDIE(clang::Decl *decl,
const lldb_private::plugin::dwarf::DWARFDIE &die);
/// If \p type_sp is valid, calculate and set its symbol context scope, and
/// update the type list for its backing symbol file.
///
/// Returns \p type_sp.
lldb::TypeSP
UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc,
const DWARFDIE &die, lldb::TypeSP type_sp);
lldb::TypeSP UpdateSymbolContextScopeForType(
const lldb_private::SymbolContext &sc,
const lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp);
/// Follow Clang Module Skeleton CU references to find a type definition.
lldb::TypeSP ParseTypeFromClangModule(const lldb_private::SymbolContext &sc,
const DWARFDIE &die,
lldb_private::Log *log);
lldb::TypeSP
ParseTypeFromClangModule(const lldb_private::SymbolContext &sc,
const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb_private::Log *log);
// Return true if this type is a declaration to a type in an external
// module.
lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
void PrepareContextToReceiveMembers(clang::DeclContext *decl_ctx,
const DWARFDIE &decl_ctx_die,
const DWARFDIE &die,
const char *type_name_cstr);
lldb::ModuleSP
GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die);
static bool classof(const DWARFASTParser *Parser) {
return Parser->GetKind() == Kind::DWARFASTParserClang;
@@ -265,8 +274,10 @@ private:
/// Parsed form of all attributes that are relevant for parsing type members.
struct MemberAttributes {
explicit MemberAttributes(const DWARFDIE &die, const DWARFDIE &parent_die,
lldb::ModuleSP module_sp);
explicit MemberAttributes(
const lldb_private::plugin::dwarf::DWARFDIE &die,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
lldb::ModuleSP module_sp);
const char *name = nullptr;
/// Indicates how many bits into the word (according to the host endianness)
/// the low-order bit of the field starts. Can be negative.
@@ -313,12 +324,15 @@ private:
/// created property.
/// \param delayed_properties The list of delayed properties that the result
/// will be appended to.
void ParseObjCProperty(const DWARFDIE &die, const DWARFDIE &parent_die,
const lldb_private::CompilerType &class_clang_type,
DelayedPropertyList &delayed_properties);
void
ParseObjCProperty(const lldb_private::plugin::dwarf::DWARFDIE &die,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
const lldb_private::CompilerType &class_clang_type,
DelayedPropertyList &delayed_properties);
void
ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die,
ParseSingleMember(const lldb_private::plugin::dwarf::DWARFDIE &die,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
const lldb_private::CompilerType &class_clang_type,
lldb::AccessType default_accessibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info,
@@ -336,25 +350,31 @@ private:
/// \param[in] class_clang_type The parent RecordType of the static
/// member this function will create.
void CreateStaticMemberVariable(
const DWARFDIE &die, const MemberAttributes &attrs,
const lldb_private::plugin::dwarf::DWARFDIE &die,
const MemberAttributes &attrs,
const lldb_private::CompilerType &class_clang_type);
bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type,
bool CompleteRecordType(const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb_private::Type *type,
lldb_private::CompilerType &clang_type);
bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type,
bool CompleteEnumType(const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb_private::Type *type,
lldb_private::CompilerType &clang_type);
lldb::TypeSP ParseTypeModifier(const lldb_private::SymbolContext &sc,
const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP
ParseTypeModifier(const lldb_private::SymbolContext &sc,
const lldb_private::plugin::dwarf::DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc,
const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP ParseSubroutine(const DWARFDIE &die,
const lldb_private::plugin::dwarf::DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP ParseSubroutine(const lldb_private::plugin::dwarf::DWARFDIE &die,
const ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP ParseArrayType(const DWARFDIE &die,
lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die,
const ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die,
const ParsedDWARFTypeAttributes &attrs);
lldb::TypeSP
ParsePointerToMemberType(const lldb_private::plugin::dwarf::DWARFDIE &die,
const ParsedDWARFTypeAttributes &attrs);
/// Parses a DW_TAG_inheritance DIE into a base/super class.
///
@@ -371,7 +391,8 @@ private:
/// \param layout_info The layout information that will be updated for C++
/// base classes with the base offset.
void ParseInheritance(
const DWARFDIE &die, const DWARFDIE &parent_die,
const lldb_private::plugin::dwarf::DWARFDIE &die,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
const lldb_private::CompilerType class_clang_type,
const lldb::AccessType default_accessibility,
const lldb::ModuleSP &module_sp,
@@ -388,7 +409,8 @@ private:
/// \param layout_info The layout information that will be updated for
// base classes with the base offset
void
ParseRustVariantPart(DWARFDIE &die, const DWARFDIE &parent_die,
ParseRustVariantPart(lldb_private::plugin::dwarf::DWARFDIE &die,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
lldb_private::CompilerType &class_clang_type,
const lldb::AccessType default_accesibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
@@ -398,9 +420,8 @@ private:
/// Some attributes are relevant for all kinds of types (declaration), while
/// others are only meaningful to a specific type (is_virtual)
struct ParsedDWARFTypeAttributes {
typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE;
explicit ParsedDWARFTypeAttributes(const DWARFDIE &die);
explicit ParsedDWARFTypeAttributes(
const lldb_private::plugin::dwarf::DWARFDIE &die);
lldb::AccessType accessibility = lldb::eAccessNone;
bool is_artificial = false;
@@ -417,7 +438,7 @@ struct ParsedDWARFTypeAttributes {
const char *mangled_name = nullptr;
lldb_private::ConstString name;
lldb_private::Declaration decl;
DWARFDIE object_pointer;
lldb_private::plugin::dwarf::DWARFDIE object_pointer;
lldb_private::plugin::dwarf::DWARFFormValue abstract_origin;
lldb_private::plugin::dwarf::DWARFFormValue containing_type;
lldb_private::plugin::dwarf::DWARFFormValue signature;

View File

@@ -85,11 +85,6 @@ bool DebugNamesDWARFIndex::ProcessEntry(
DWARFDIE die = GetDIE(entry);
if (!die)
return true;
// Clang erroneously emits index entries for declaration DIEs in case when the
// definition is in a type unit (llvm.org/pr77696). Weed those out.
if (die.IsStructUnionOrClass() &&
die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
return true;
return callback(die);
}

View File

@@ -481,13 +481,6 @@ static ConstString GetDWARFMachOSegmentName() {
return g_dwarf_section_name;
}
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
SymbolFileDWARF::GetForwardDeclCompilerTypeToDIE() {
if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
return debug_map_symfile->GetForwardDeclCompilerTypeToDIE();
return m_forward_decl_compiler_type_to_die;
}
UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() {
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile)
@@ -1639,33 +1632,27 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
return true;
}
// Once we start resolving this type, remove it from the forward
// declaration map in case anyone's child members or other types require this
// type to get resolved.
DWARFDIE dwarf_die = GetDIE(die_it->second);
GetForwardDeclCompilerTypeToDIE().erase(die_it);
Type *type = nullptr;
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
type = dwarf_ast->FindDefinitionTypeForDIE(dwarf_die);
if (!type)
return false;
die_it = GetForwardDeclCompilerTypeToDIE().find(
compiler_type_no_qualifiers.GetOpaqueQualType());
if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
dwarf_die = GetDIE(die_it->getSecond());
DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
if (dwarf_die) {
// Once we start resolving this type, remove it from the forward
// declaration map in case anyone child members or other types require this
// type to get resolved. The type will get resolved when all of the calls
// to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
GetForwardDeclCompilerTypeToDIE().erase(die_it);
}
if (Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion))
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()),
dwarf_die.Tag(), type->GetName().AsCString());
assert(compiler_type);
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
return true;
Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
if (log)
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()),
dwarf_die.Tag(), type->GetName().AsCString());
assert(compiler_type);
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
}
return false;
}
Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,

View File

@@ -335,8 +335,12 @@ public:
virtual DIEToTypePtr &GetDIEToType() { return m_die_to_type; }
virtual llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
GetForwardDeclCompilerTypeToDIE();
typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
CompilerTypeToDIE;
virtual CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() {
return m_forward_decl_compiler_type_to_die;
}
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
DIEToVariableSP;
@@ -529,14 +533,9 @@ protected:
NameToOffsetMap m_function_scope_qualified_name_map;
std::unique_ptr<DWARFDebugRanges> m_ranges;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
// A map from DIE to lldb_private::Type. For record type, the key might be
// either declaration DIE or definition DIE.
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
// A map from CompilerType to the struct/class/union/enum DIE (might be a
// declaration or a definition) that is used to construct it.
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
m_forward_decl_compiler_type_to_die;
CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
llvm::DenseMap<dw_offset_t, std::unique_ptr<SupportFileList>>
m_type_unit_support_files;
std::vector<uint32_t> m_lldb_cu_to_dwarf_unit;

View File

@@ -284,11 +284,6 @@ protected:
lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE(
const DWARFDIE &die, ConstString type_name, bool must_be_implementation);
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
GetForwardDeclCompilerTypeToDIE() {
return m_forward_decl_compiler_type_to_die;
}
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() {
return m_unique_ast_type_map;
}
@@ -326,10 +321,6 @@ protected:
std::vector<uint32_t> m_func_indexes; // Sorted by address
std::vector<uint32_t> m_glob_indexes;
std::map<std::pair<ConstString, llvm::sys::TimePoint<>>, OSOInfoSP> m_oso_map;
// A map from CompilerType to the struct/class/union/enum DIE (might be a
// declaration or a definition) that is used to construct it.
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
m_forward_decl_compiler_type_to_die;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
DebugMap m_debug_map;

View File

@@ -110,7 +110,7 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
return GetBaseSymbolFile().GetDIEToVariable();
}
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
SymbolFileDWARF::CompilerTypeToDIE &
SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() {
return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE();
}

View File

@@ -72,8 +72,7 @@ protected:
DIEToVariableSP &GetDIEToVariable() override;
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
GetForwardDeclCompilerTypeToDIE() override;
CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;

View File

@@ -13,75 +13,66 @@
using namespace lldb_private::dwarf;
using namespace lldb_private::plugin::dwarf;
static bool IsStructOrClassTag(llvm::dwarf::Tag Tag) {
return Tag == llvm::dwarf::Tag::DW_TAG_class_type ||
Tag == llvm::dwarf::Tag::DW_TAG_structure_type;
}
UniqueDWARFASTType *UniqueDWARFASTTypeList::Find(
const DWARFDIE &die, const lldb_private::Declaration &decl,
const int32_t byte_size, bool is_forward_declaration) {
for (UniqueDWARFASTType &udt : m_collection) {
bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
const lldb_private::Declaration &decl,
const int32_t byte_size,
UniqueDWARFASTType &entry) const {
for (const UniqueDWARFASTType &udt : m_collection) {
// Make sure the tags match
if (udt.m_die.Tag() == die.Tag() || (IsStructOrClassTag(udt.m_die.Tag()) &&
IsStructOrClassTag(die.Tag()))) {
// If they are not both definition DIEs or both declaration DIEs, then
// don't check for byte size and declaration location, because declaration
// DIEs usually don't have those info.
bool matching_size_declaration =
udt.m_is_forward_declaration != is_forward_declaration
? true
: (udt.m_byte_size < 0 || byte_size < 0 ||
udt.m_byte_size == byte_size) &&
udt.m_declaration == decl;
if (!matching_size_declaration)
continue;
// The type has the same name, and was defined on the same file and
// line. Now verify all of the parent DIEs match.
DWARFDIE parent_arg_die = die.GetParent();
DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
bool done = false;
while (!done && match && parent_arg_die && parent_pos_die) {
const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
if (parent_arg_tag == parent_pos_tag ||
(IsStructOrClassTag(parent_arg_tag) &&
IsStructOrClassTag(parent_pos_tag))) {
switch (parent_arg_tag) {
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_namespace: {
const char *parent_arg_die_name = parent_arg_die.GetName();
if (parent_arg_die_name == nullptr) {
// Anonymous (i.e. no-name) struct
match = false;
} else {
const char *parent_pos_die_name = parent_pos_die.GetName();
if (parent_pos_die_name == nullptr ||
((parent_arg_die_name != parent_pos_die_name) &&
strcmp(parent_arg_die_name, parent_pos_die_name)))
match = false;
}
} break;
if (udt.m_die.Tag() == die.Tag()) {
// Validate byte sizes of both types only if both are valid.
if (udt.m_byte_size < 0 || byte_size < 0 ||
udt.m_byte_size == byte_size) {
// Make sure the file and line match
if (udt.m_declaration == decl) {
// The type has the same name, and was defined on the same file and
// line. Now verify all of the parent DIEs match.
DWARFDIE parent_arg_die = die.GetParent();
DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
bool done = false;
while (!done && match && parent_arg_die && parent_pos_die) {
const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
if (parent_arg_tag == parent_pos_tag) {
switch (parent_arg_tag) {
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_namespace: {
const char *parent_arg_die_name = parent_arg_die.GetName();
if (parent_arg_die_name ==
nullptr) // Anonymous (i.e. no-name) struct
{
match = false;
} else {
const char *parent_pos_die_name = parent_pos_die.GetName();
if (parent_pos_die_name == nullptr ||
((parent_arg_die_name != parent_pos_die_name) &&
strcmp(parent_arg_die_name, parent_pos_die_name)))
match = false;
}
} break;
case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
done = true;
break;
default:
break;
case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
done = true;
break;
default:
break;
}
}
parent_arg_die = parent_arg_die.GetParent();
parent_pos_die = parent_pos_die.GetParent();
}
if (match) {
entry = udt;
return true;
}
}
parent_arg_die = parent_arg_die.GetParent();
parent_pos_die = parent_pos_die.GetParent();
}
if (match) {
return &udt;
}
}
}
return nullptr;
return false;
}

View File

@@ -23,19 +23,31 @@ public:
// Constructors and Destructors
UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {}
UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die,
const Declaration &decl, int32_t byte_size)
: m_type_sp(type_sp), m_die(die), m_declaration(decl),
m_byte_size(byte_size) {}
UniqueDWARFASTType(const UniqueDWARFASTType &rhs)
: m_type_sp(rhs.m_type_sp), m_die(rhs.m_die),
m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size),
m_is_forward_declaration(rhs.m_is_forward_declaration) {}
m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {}
~UniqueDWARFASTType() = default;
UniqueDWARFASTType &operator=(const UniqueDWARFASTType &rhs) {
if (this != &rhs) {
m_type_sp = rhs.m_type_sp;
m_die = rhs.m_die;
m_declaration = rhs.m_declaration;
m_byte_size = rhs.m_byte_size;
}
return *this;
}
lldb::TypeSP m_type_sp;
DWARFDIE m_die;
Declaration m_declaration;
int32_t m_byte_size = -1;
// True if the m_die is a forward declaration DIE.
bool m_is_forward_declaration = true;
};
class UniqueDWARFASTTypeList {
@@ -50,9 +62,8 @@ public:
m_collection.push_back(entry);
}
UniqueDWARFASTType *Find(const DWARFDIE &die, const Declaration &decl,
const int32_t byte_size,
bool is_forward_declaration);
bool Find(const DWARFDIE &die, const Declaration &decl,
const int32_t byte_size, UniqueDWARFASTType &entry) const;
protected:
typedef std::vector<UniqueDWARFASTType> collection;
@@ -69,15 +80,14 @@ public:
m_collection[name.GetCString()].Append(entry);
}
UniqueDWARFASTType *Find(ConstString name, const DWARFDIE &die,
const Declaration &decl, const int32_t byte_size,
bool is_forward_declaration) {
bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl,
const int32_t byte_size, UniqueDWARFASTType &entry) const {
const char *unique_name_cstr = name.GetCString();
collection::iterator pos = m_collection.find(unique_name_cstr);
collection::const_iterator pos = m_collection.find(unique_name_cstr);
if (pos != m_collection.end()) {
return pos->second.Find(die, decl, byte_size, is_forward_declaration);
return pos->second.Find(die, decl, byte_size, entry);
}
return nullptr;
return false;
}
protected:

View File

@@ -1,36 +0,0 @@
# Test definition DIE searching is delayed until complete type is required.
# UNSUPPORTED: system-windows
# RUN: split-file %s %t
# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -gdwarf -o %t.out
# RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s
# CHECK: (lldb) p v1
# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2<t1>'
# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't2<t1>' resolving forward declaration...
# CHECK: (t2<t1>) {}
# CHECK: (lldb) p v2
# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration...
#--- lldb.cmd
log enable dwarf comp
p v1
p v2
#--- main.cpp
template<typename T>
struct t2 {
};
struct t1;
t2<t1> v1; // this CU doesn't have definition DIE for t1, but only declaration DIE for it.
int main() {
}
#--- t1_def.cpp
struct t1 { // this CU contains definition DIE for t1.
int x;
};
t1 v2;