mirror of
https://github.com/intel/llvm.git
synced 2026-01-22 23:49:22 +08:00
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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -72,8 +72,7 @@ protected:
|
||||
|
||||
DIEToVariableSP &GetDIEToVariable() override;
|
||||
|
||||
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
|
||||
GetForwardDeclCompilerTypeToDIE() override;
|
||||
CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
|
||||
|
||||
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user