forked from OSchip/llvm-project
[DWARFASTParserClang] Factor out structure-like type parsing, NFC
Split out the logic to parse structure-like types into a separate function, in an attempt to reduce the complexity of ParseTypeFromDWARF. Inspired by discussion in https://reviews.llvm.org/D68130. Differential Revision: https://reviews.llvm.org/D68422 llvm-svn: 373927
This commit is contained in:
parent
fccfe2c04a
commit
40a1853c49
|
@ -28,7 +28,6 @@ public:
|
|||
|
||||
virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
|
||||
const DWARFDIE &die,
|
||||
lldb_private::Log *log,
|
||||
bool *type_is_new_ptr) = 0;
|
||||
|
||||
virtual lldb_private::Function *
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "DWARFASTParserClang.h"
|
||||
#include "DWARFDIE.h"
|
||||
#include "DWARFDebugInfo.h"
|
||||
#include "DWARFDeclContext.h"
|
||||
#include "DWARFDefines.h"
|
||||
|
@ -232,42 +231,7 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// Parsed form of all attributes that are relevant for type reconstruction.
|
||||
/// Some attributes are relevant for all kinds of types (declaration), while
|
||||
/// others are only meaningful to a specific type (is_virtual)
|
||||
struct ParsedTypeAttributes {
|
||||
explicit ParsedTypeAttributes(const DWARFDIE &die);
|
||||
|
||||
AccessType accessibility = eAccessNone;
|
||||
bool is_artificial = false;
|
||||
bool is_complete_objc_class = false;
|
||||
bool is_explicit = false;
|
||||
bool is_forward_declaration = false;
|
||||
bool is_inline = false;
|
||||
bool is_scoped_enum = false;
|
||||
bool is_vector = false;
|
||||
bool is_virtual = false;
|
||||
clang::StorageClass storage = clang::SC_None;
|
||||
const char *mangled_name = nullptr;
|
||||
ConstString name;
|
||||
Declaration decl;
|
||||
DWARFDIE object_pointer;
|
||||
DWARFFormValue abstract_origin;
|
||||
DWARFFormValue containing_type;
|
||||
DWARFFormValue signature;
|
||||
DWARFFormValue specification;
|
||||
DWARFFormValue type;
|
||||
LanguageType class_language = eLanguageTypeUnknown;
|
||||
llvm::Optional<uint64_t> byte_size;
|
||||
size_t calling_convention = llvm::dwarf::DW_CC_normal;
|
||||
uint32_t bit_stride = 0;
|
||||
uint32_t byte_stride = 0;
|
||||
uint32_t encoding = 0;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die) {
|
||||
ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
|
||||
DWARFAttributes attributes;
|
||||
size_t num_attributes = die.GetAttributes(attributes);
|
||||
for (size_t i = 0; i < num_attributes; ++i) {
|
||||
|
@ -394,13 +358,17 @@ static std::string GetUnitName(const DWARFDIE &die) {
|
|||
}
|
||||
|
||||
TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
|
||||
const DWARFDIE &die, Log *log,
|
||||
const DWARFDIE &die,
|
||||
bool *type_is_new_ptr) {
|
||||
if (type_is_new_ptr)
|
||||
*type_is_new_ptr = false;
|
||||
|
||||
if (!die)
|
||||
return nullptr;
|
||||
|
||||
Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
|
||||
DWARF_LOG_LOOKUPS));
|
||||
|
||||
SymbolFileDWARF *dwarf = die.GetDWARF();
|
||||
if (log) {
|
||||
DWARFDIE context_die;
|
||||
|
@ -424,11 +392,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
|
|||
// Set a bit that lets us know that we are currently parsing this
|
||||
dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
|
||||
|
||||
ParsedTypeAttributes attrs(die);
|
||||
ParsedDWARFTypeAttributes attrs(die);
|
||||
|
||||
if (DWARFDIE signature_die = attrs.signature.Reference()) {
|
||||
if (TypeSP type_sp =
|
||||
ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) {
|
||||
ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) {
|
||||
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
|
||||
if (clang::DeclContext *decl_ctx =
|
||||
GetCachedClangDeclContextForDIE(signature_die))
|
||||
|
@ -438,7 +406,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TypeList &type_list = dwarf->GetTypeList();
|
||||
if (type_is_new_ptr)
|
||||
*type_is_new_ptr = true;
|
||||
|
||||
|
@ -566,7 +533,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
|
|||
|
||||
bool function_type_is_new_pointer;
|
||||
TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
|
||||
sc, function_type, log, &function_type_is_new_pointer);
|
||||
sc, function_type, &function_type_is_new_pointer);
|
||||
|
||||
if (lldb_function_type_sp) {
|
||||
clang_type = m_ast.CreateBlockPointerType(
|
||||
|
@ -664,372 +631,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
|
|||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type:
|
||||
case DW_TAG_class_type: {
|
||||
// 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 and sharing the stack space for
|
||||
// variables in different blocks.
|
||||
std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_up(
|
||||
new 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;
|
||||
if (die.GetQualifiedName(qualified_name))
|
||||
unique_typename = ConstString(qualified_name);
|
||||
unique_decl.Clear();
|
||||
}
|
||||
|
||||
if (dwarf->GetUniqueDWARFASTTypeMap().Find(
|
||||
unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = clang::TTK_Struct;
|
||||
default_accessibility = eAccessPublic;
|
||||
} else if (tag == DW_TAG_union_type) {
|
||||
tag_decl_kind = clang::TTK_Union;
|
||||
default_accessibility = eAccessPublic;
|
||||
} else if (tag == DW_TAG_class_type) {
|
||||
tag_decl_kind = clang::TTK_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 &&
|
||||
die.Supports_DW_AT_APPLE_objc_complete_type()) {
|
||||
// We have a valid eSymbolTypeObjCClass class symbol whose name
|
||||
// matches the current objective C class that we are trying to find
|
||||
// and this DIE isn't the complete definition (we checked
|
||||
// is_complete_objc_class above and know it is false), so the real
|
||||
// definition is in here somewhere
|
||||
type_sp =
|
||||
dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
|
||||
|
||||
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->FindCompleteObjCDefinitionTypeForDIE(
|
||||
die, attrs.name, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_sp) {
|
||||
if (log) {
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessage(
|
||||
log,
|
||||
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an "
|
||||
"incomplete objc type, complete type is 0x%8.8" PRIx64,
|
||||
static_cast<void *>(this), die.GetOffset(),
|
||||
DW_TAG_value_to_name(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(%p) - 0x%8.8x: %s type \"%s\" is a "
|
||||
"forward declaration, trying to find complete type",
|
||||
static_cast<void *>(this), die.GetOffset(),
|
||||
DW_TAG_value_to_name(tag), attrs.name.GetCString());
|
||||
}
|
||||
|
||||
// See if the type comes from a DWO module and if so, track down that
|
||||
// type.
|
||||
type_sp = ParseTypeFromDWO(die, log);
|
||||
if (type_sp)
|
||||
return type_sp;
|
||||
|
||||
DWARFDeclContext die_decl_ctx;
|
||||
die.GetDWARFDeclContext(die_decl_ctx);
|
||||
|
||||
// type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
|
||||
// type_name_const_str);
|
||||
type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
|
||||
|
||||
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_decl_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_sp) {
|
||||
if (log) {
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessage(
|
||||
log,
|
||||
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
|
||||
"forward declaration, complete type is 0x%8.8" PRIx64,
|
||||
static_cast<void *>(this), die.GetOffset(),
|
||||
DW_TAG_value_to_name(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);
|
||||
bool clang_type_was_created = false;
|
||||
clang_type.SetCompilerType(
|
||||
&m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
|
||||
if (!clang_type) {
|
||||
clang::DeclContext *decl_ctx =
|
||||
GetClangDeclContextContainingDIE(die, nullptr);
|
||||
|
||||
// If your decl context is a record that was imported from another
|
||||
// AST context (in the gmodules case), we need to make sure the type
|
||||
// backing the Decl is complete before adding children to it. This is
|
||||
// not an issue in the non-gmodules case because the debug info will
|
||||
// always contain a full definition of parent types in that case.
|
||||
CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
|
||||
attrs.name.GetCString());
|
||||
|
||||
if (attrs.accessibility == eAccessNone && decl_ctx) {
|
||||
// Check the decl context that contains this class/struct/union. If
|
||||
// it is a class we must give it an accessibility.
|
||||
const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
|
||||
if (DeclKindIsCXXClass(containing_decl_kind))
|
||||
attrs.accessibility = default_accessibility;
|
||||
}
|
||||
|
||||
ClangASTMetadata metadata;
|
||||
metadata.SetUserID(die.GetID());
|
||||
metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die));
|
||||
|
||||
if (attrs.name.GetStringRef().contains('<')) {
|
||||
ClangASTContext::TemplateParameterInfos template_param_infos;
|
||||
if (ParseTemplateParameterInfos(die, template_param_infos)) {
|
||||
clang::ClassTemplateDecl *class_template_decl =
|
||||
m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility,
|
||||
attrs.name.GetCString(),
|
||||
tag_decl_kind, template_param_infos);
|
||||
if (!class_template_decl) {
|
||||
if (log) {
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessage(
|
||||
log,
|
||||
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" "
|
||||
"clang::ClassTemplateDecl failed to return a decl.",
|
||||
static_cast<void *>(this), die.GetOffset(),
|
||||
DW_TAG_value_to_name(tag), attrs.name.GetCString());
|
||||
}
|
||||
return TypeSP();
|
||||
}
|
||||
|
||||
clang::ClassTemplateSpecializationDecl *class_specialization_decl =
|
||||
m_ast.CreateClassTemplateSpecializationDecl(
|
||||
decl_ctx, class_template_decl, 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_was_created) {
|
||||
clang_type_was_created = true;
|
||||
clang_type = m_ast.CreateRecordType(
|
||||
decl_ctx, attrs.accessibility, attrs.name.GetCString(),
|
||||
tag_decl_kind, attrs.class_language, &metadata);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
|
||||
type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
|
||||
attrs.byte_size, nullptr, LLDB_INVALID_UID,
|
||||
Type::eEncodingIsUID, &attrs.decl, clang_type,
|
||||
Type::eResolveStateForward);
|
||||
|
||||
type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class);
|
||||
|
||||
// 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 = attrs.byte_size.getValueOr(0);
|
||||
dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
|
||||
*unique_ast_entry_up);
|
||||
|
||||
if (attrs.is_forward_declaration && die.HasChildren()) {
|
||||
// Check to see if the DIE actually has a definition, some version of
|
||||
// GCC will
|
||||
// emit DIEs with DW_AT_declaration set to true, but yet still have
|
||||
// subprogram, members, or inheritance, so we can't trust it
|
||||
DWARFDIE child_die = die.GetFirstChild();
|
||||
while (child_die) {
|
||||
switch (child_die.Tag()) {
|
||||
case DW_TAG_inheritance:
|
||||
case DW_TAG_subprogram:
|
||||
case DW_TAG_member:
|
||||
case DW_TAG_APPLE_property:
|
||||
case DW_TAG_class_type:
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_enumeration_type:
|
||||
case DW_TAG_typedef:
|
||||
case DW_TAG_union_type:
|
||||
child_die.Clear();
|
||||
attrs.is_forward_declaration = false;
|
||||
break;
|
||||
default:
|
||||
child_die = child_die.GetSibling();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!attrs.is_forward_declaration) {
|
||||
// Always start the definition for a class type so that if the class
|
||||
// has child classes or types that require the class to be created
|
||||
// for use as their decl contexts the class will be ready to accept
|
||||
// these child definitions.
|
||||
if (!die.HasChildren()) {
|
||||
// No children for this struct/union/class, lets finish it
|
||||
if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
|
||||
ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
|
||||
} else {
|
||||
dwarf->GetObjectFile()->GetModule()->ReportError(
|
||||
"DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
|
||||
"definition.\nPlease file a bug and attach the file at the "
|
||||
"start of this error message",
|
||||
die.GetOffset(), attrs.name.GetCString());
|
||||
}
|
||||
|
||||
if (tag == DW_TAG_structure_type) // this only applies in C
|
||||
{
|
||||
clang::RecordDecl *record_decl =
|
||||
ClangASTContext::GetAsRecordDecl(clang_type);
|
||||
|
||||
if (record_decl) {
|
||||
GetClangASTImporter().InsertRecordDecl(
|
||||
record_decl, ClangASTImporter::LayoutInfo());
|
||||
}
|
||||
}
|
||||
} 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
|
||||
// start the declaration definition right away. For C++
|
||||
// class/union/structs we want to start the definition in case the
|
||||
// class is needed as the declaration context for a contained class
|
||||
// or type without the need to complete that type..
|
||||
|
||||
if (attrs.class_language != eLanguageTypeObjC &&
|
||||
attrs.class_language != eLanguageTypeObjC_plus_plus)
|
||||
ClangASTContext::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->GetForwardDeclClangTypeToDie().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->GetForwardDeclDieToClangType()[die.GetDIE()] =
|
||||
clang_type.GetOpaqueQualType();
|
||||
dwarf->GetForwardDeclClangTypeToDie()
|
||||
[ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] =
|
||||
die.GetID();
|
||||
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
|
||||
// value is pass by reference, so we ignore that attribute if set.
|
||||
if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
|
||||
clang::CXXRecordDecl *record_decl =
|
||||
m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
|
||||
if (record_decl && record_decl->getDefinition()) {
|
||||
record_decl->setHasTrivialSpecialMemberForCall();
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) {
|
||||
clang::CXXRecordDecl *record_decl =
|
||||
m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
|
||||
if (record_decl)
|
||||
record_decl->setArgPassingRestrictions(
|
||||
clang::RecordDecl::APK_CannotPassInRegs);
|
||||
}
|
||||
|
||||
} break;
|
||||
assert((!type_sp && !clang_type) &&
|
||||
"Did not expect partially computed structure-like type");
|
||||
TypeSP struct_like_type_sp = ParseStructureLikeDIE(die, attrs);
|
||||
return UpdateSymbolContextScopeForType(sc, die, struct_like_type_sp);
|
||||
}
|
||||
|
||||
case DW_TAG_enumeration_type: {
|
||||
if (attrs.is_forward_declaration) {
|
||||
|
@ -1656,31 +1262,418 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
|
|||
break;
|
||||
}
|
||||
|
||||
if (type_sp.get()) {
|
||||
DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
|
||||
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
|
||||
// TODO: We should consider making the switch above exhaustive to simplify
|
||||
// control flow in ParseTypeFromDWARF. Then, we could simply replace this
|
||||
// return statement with a call to llvm_unreachable.
|
||||
return UpdateSymbolContextScopeForType(sc, die, type_sp);
|
||||
}
|
||||
|
||||
SymbolContextScope *symbol_context_scope = NULL;
|
||||
if (sc_parent_tag == DW_TAG_compile_unit ||
|
||||
sc_parent_tag == DW_TAG_partial_unit) {
|
||||
symbol_context_scope = sc.comp_unit;
|
||||
} else if (sc.function != NULL && sc_parent_die) {
|
||||
symbol_context_scope =
|
||||
sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
|
||||
if (symbol_context_scope == NULL)
|
||||
symbol_context_scope = sc.function;
|
||||
} else
|
||||
symbol_context_scope = sc.module_sp.get();
|
||||
TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
|
||||
const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) {
|
||||
if (!type_sp)
|
||||
return type_sp;
|
||||
|
||||
if (symbol_context_scope != NULL) {
|
||||
type_sp->SetSymbolContextScope(symbol_context_scope);
|
||||
SymbolFileDWARF *dwarf = die.GetDWARF();
|
||||
TypeList &type_list = dwarf->GetTypeList();
|
||||
DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
|
||||
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
|
||||
|
||||
SymbolContextScope *symbol_context_scope = NULL;
|
||||
if (sc_parent_tag == DW_TAG_compile_unit ||
|
||||
sc_parent_tag == DW_TAG_partial_unit) {
|
||||
symbol_context_scope = sc.comp_unit;
|
||||
} else if (sc.function != NULL && sc_parent_die) {
|
||||
symbol_context_scope =
|
||||
sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
|
||||
if (symbol_context_scope == NULL)
|
||||
symbol_context_scope = sc.function;
|
||||
} else {
|
||||
symbol_context_scope = sc.module_sp.get();
|
||||
}
|
||||
|
||||
if (symbol_context_scope != NULL)
|
||||
type_sp->SetSymbolContextScope(symbol_context_scope);
|
||||
|
||||
// We are ready to put this type into the uniqued list up at the module
|
||||
// level.
|
||||
type_list.Insert(type_sp);
|
||||
|
||||
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
|
||||
return type_sp;
|
||||
}
|
||||
|
||||
TypeSP
|
||||
DWARFASTParserClang::ParseStructureLikeDIE(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 = die.GetLanguage();
|
||||
Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_TYPE_COMPLETION |
|
||||
DWARF_LOG_LOOKUPS);
|
||||
|
||||
// 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;
|
||||
if (die.GetQualifiedName(qualified_name))
|
||||
unique_typename = ConstString(qualified_name);
|
||||
unique_decl.Clear();
|
||||
}
|
||||
|
||||
// We are ready to put this type into the uniqued list up at the module
|
||||
// level
|
||||
type_list.Insert(type_sp);
|
||||
if (dwarf->GetUniqueDWARFASTTypeMap().Find(
|
||||
unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
|
||||
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 = clang::TTK_Struct;
|
||||
default_accessibility = eAccessPublic;
|
||||
} else if (tag == DW_TAG_union_type) {
|
||||
tag_decl_kind = clang::TTK_Union;
|
||||
default_accessibility = eAccessPublic;
|
||||
} else if (tag == DW_TAG_class_type) {
|
||||
tag_decl_kind = clang::TTK_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 &&
|
||||
die.Supports_DW_AT_APPLE_objc_complete_type()) {
|
||||
// We have a valid eSymbolTypeObjCClass class symbol whose name
|
||||
// matches the current objective C class that we are trying to find
|
||||
// and this DIE isn't the complete definition (we checked
|
||||
// is_complete_objc_class above and know it is false), so the real
|
||||
// definition is in here somewhere
|
||||
type_sp =
|
||||
dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
|
||||
|
||||
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->FindCompleteObjCDefinitionTypeForDIE(
|
||||
die, attrs.name, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_sp) {
|
||||
if (log) {
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessage(
|
||||
log,
|
||||
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an "
|
||||
"incomplete objc type, complete type is 0x%8.8" PRIx64,
|
||||
static_cast<void *>(this), die.GetOffset(),
|
||||
DW_TAG_value_to_name(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(%p) - 0x%8.8x: %s type \"%s\" is a "
|
||||
"forward declaration, trying to find complete type",
|
||||
static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
|
||||
attrs.name.GetCString());
|
||||
}
|
||||
|
||||
// See if the type comes from a DWO module and if so, track down that
|
||||
// type.
|
||||
type_sp = ParseTypeFromDWO(die, log);
|
||||
if (type_sp)
|
||||
return type_sp;
|
||||
|
||||
DWARFDeclContext die_decl_ctx;
|
||||
die.GetDWARFDeclContext(die_decl_ctx);
|
||||
|
||||
// type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
|
||||
// type_name_const_str);
|
||||
type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
|
||||
|
||||
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_decl_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_sp) {
|
||||
if (log) {
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessage(
|
||||
log,
|
||||
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
|
||||
"forward declaration, complete type is 0x%8.8" PRIx64,
|
||||
static_cast<void *>(this), die.GetOffset(),
|
||||
DW_TAG_value_to_name(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);
|
||||
bool clang_type_was_created = false;
|
||||
clang_type.SetCompilerType(
|
||||
&m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
|
||||
if (!clang_type) {
|
||||
clang::DeclContext *decl_ctx =
|
||||
GetClangDeclContextContainingDIE(die, nullptr);
|
||||
|
||||
// If your decl context is a record that was imported from another
|
||||
// AST context (in the gmodules case), we need to make sure the type
|
||||
// backing the Decl is complete before adding children to it. This is
|
||||
// not an issue in the non-gmodules case because the debug info will
|
||||
// always contain a full definition of parent types in that case.
|
||||
CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
|
||||
attrs.name.GetCString());
|
||||
|
||||
if (attrs.accessibility == eAccessNone && decl_ctx) {
|
||||
// Check the decl context that contains this class/struct/union. If
|
||||
// it is a class we must give it an accessibility.
|
||||
const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
|
||||
if (DeclKindIsCXXClass(containing_decl_kind))
|
||||
attrs.accessibility = default_accessibility;
|
||||
}
|
||||
|
||||
ClangASTMetadata metadata;
|
||||
metadata.SetUserID(die.GetID());
|
||||
metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die));
|
||||
|
||||
if (attrs.name.GetStringRef().contains('<')) {
|
||||
ClangASTContext::TemplateParameterInfos template_param_infos;
|
||||
if (ParseTemplateParameterInfos(die, template_param_infos)) {
|
||||
clang::ClassTemplateDecl *class_template_decl =
|
||||
m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility,
|
||||
attrs.name.GetCString(), tag_decl_kind,
|
||||
template_param_infos);
|
||||
if (!class_template_decl) {
|
||||
if (log) {
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessage(
|
||||
log,
|
||||
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" "
|
||||
"clang::ClassTemplateDecl failed to return a decl.",
|
||||
static_cast<void *>(this), die.GetOffset(),
|
||||
DW_TAG_value_to_name(tag), attrs.name.GetCString());
|
||||
}
|
||||
return TypeSP();
|
||||
}
|
||||
|
||||
clang::ClassTemplateSpecializationDecl *class_specialization_decl =
|
||||
m_ast.CreateClassTemplateSpecializationDecl(
|
||||
decl_ctx, class_template_decl, 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_was_created) {
|
||||
clang_type_was_created = true;
|
||||
clang_type = m_ast.CreateRecordType(
|
||||
decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind,
|
||||
attrs.class_language, &metadata);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
|
||||
type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
|
||||
attrs.byte_size, nullptr, LLDB_INVALID_UID,
|
||||
Type::eEncodingIsUID, &attrs.decl,
|
||||
clang_type, Type::eResolveStateForward);
|
||||
|
||||
type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class);
|
||||
|
||||
// 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 = attrs.byte_size.getValueOr(0);
|
||||
dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
|
||||
*unique_ast_entry_up);
|
||||
|
||||
if (attrs.is_forward_declaration && die.HasChildren()) {
|
||||
// Check to see if the DIE actually has a definition, some version of
|
||||
// GCC will
|
||||
// emit DIEs with DW_AT_declaration set to true, but yet still have
|
||||
// subprogram, members, or inheritance, so we can't trust it
|
||||
DWARFDIE child_die = die.GetFirstChild();
|
||||
while (child_die) {
|
||||
switch (child_die.Tag()) {
|
||||
case DW_TAG_inheritance:
|
||||
case DW_TAG_subprogram:
|
||||
case DW_TAG_member:
|
||||
case DW_TAG_APPLE_property:
|
||||
case DW_TAG_class_type:
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_enumeration_type:
|
||||
case DW_TAG_typedef:
|
||||
case DW_TAG_union_type:
|
||||
child_die.Clear();
|
||||
attrs.is_forward_declaration = false;
|
||||
break;
|
||||
default:
|
||||
child_die = child_die.GetSibling();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!attrs.is_forward_declaration) {
|
||||
// Always start the definition for a class type so that if the class
|
||||
// has child classes or types that require the class to be created
|
||||
// for use as their decl contexts the class will be ready to accept
|
||||
// these child definitions.
|
||||
if (!die.HasChildren()) {
|
||||
// No children for this struct/union/class, lets finish it
|
||||
if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
|
||||
ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
|
||||
} else {
|
||||
dwarf->GetObjectFile()->GetModule()->ReportError(
|
||||
"DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
|
||||
"definition.\nPlease file a bug and attach the file at the "
|
||||
"start of this error message",
|
||||
die.GetOffset(), attrs.name.GetCString());
|
||||
}
|
||||
|
||||
if (tag == DW_TAG_structure_type) // this only applies in C
|
||||
{
|
||||
clang::RecordDecl *record_decl =
|
||||
ClangASTContext::GetAsRecordDecl(clang_type);
|
||||
|
||||
if (record_decl) {
|
||||
GetClangASTImporter().InsertRecordDecl(
|
||||
record_decl, ClangASTImporter::LayoutInfo());
|
||||
}
|
||||
}
|
||||
} 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
|
||||
// start the declaration definition right away. For C++
|
||||
// class/union/structs we want to start the definition in case the
|
||||
// class is needed as the declaration context for a contained class
|
||||
// or type without the need to complete that type..
|
||||
|
||||
if (attrs.class_language != eLanguageTypeObjC &&
|
||||
attrs.class_language != eLanguageTypeObjC_plus_plus)
|
||||
ClangASTContext::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->GetForwardDeclClangTypeToDie().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->GetForwardDeclDieToClangType()[die.GetDIE()] =
|
||||
clang_type.GetOpaqueQualType();
|
||||
dwarf->GetForwardDeclClangTypeToDie()
|
||||
[ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] =
|
||||
die.GetID();
|
||||
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
|
||||
// value is pass by reference, so we ignore that attribute if set.
|
||||
if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
|
||||
clang::CXXRecordDecl *record_decl =
|
||||
m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
|
||||
if (record_decl && record_decl->getDefinition()) {
|
||||
record_decl->setHasTrivialSpecialMemberForCall();
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) {
|
||||
clang::CXXRecordDecl *record_decl =
|
||||
m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
|
||||
if (record_decl)
|
||||
record_decl->setArgPassingRestrictions(
|
||||
clang::RecordDecl::APK_CannotPassInRegs);
|
||||
}
|
||||
return type_sp;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
#include "DWARFASTParser.h"
|
||||
#include "DWARFDIE.h"
|
||||
#include "DWARFDefines.h"
|
||||
#include "DWARFFormValue.h"
|
||||
#include "LogChannelDWARF.h"
|
||||
#include "lldb/Core/ClangForward.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
|
@ -29,6 +32,8 @@ class CompileUnit;
|
|||
class DWARFDebugInfoEntry;
|
||||
class SymbolFileDWARF;
|
||||
|
||||
struct ParsedDWARFTypeAttributes;
|
||||
|
||||
class DWARFASTParserClang : public DWARFASTParser {
|
||||
public:
|
||||
DWARFASTParserClang(lldb_private::ClangASTContext &ast);
|
||||
|
@ -37,7 +42,7 @@ public:
|
|||
|
||||
// DWARFASTParser interface.
|
||||
lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
|
||||
const DWARFDIE &die, lldb_private::Log *log,
|
||||
const DWARFDIE &die,
|
||||
bool *type_is_new_ptr) override;
|
||||
|
||||
lldb_private::Function *
|
||||
|
@ -122,6 +127,10 @@ protected:
|
|||
bool is_signed, uint32_t enumerator_byte_size,
|
||||
const DWARFDIE &parent_die);
|
||||
|
||||
/// Parse a structure, class, or union type DIE.
|
||||
lldb::TypeSP ParseStructureLikeDIE(const DWARFDIE &die,
|
||||
ParsedDWARFTypeAttributes &attrs);
|
||||
|
||||
lldb_private::Type *GetTypeForDIE(const DWARFDIE &die);
|
||||
|
||||
clang::Decl *GetClangDeclForDIE(const DWARFDIE &die);
|
||||
|
@ -142,6 +151,14 @@ protected:
|
|||
|
||||
void LinkDeclToDIE(clang::Decl *decl, const 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 ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log);
|
||||
|
||||
// Return true if this type is a declaration to a type in an external
|
||||
|
@ -149,4 +166,37 @@ protected:
|
|||
lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
|
||||
};
|
||||
|
||||
/// Parsed form of all attributes that are relevant for type reconstruction.
|
||||
/// Some attributes are relevant for all kinds of types (declaration), while
|
||||
/// others are only meaningful to a specific type (is_virtual)
|
||||
struct ParsedDWARFTypeAttributes {
|
||||
explicit ParsedDWARFTypeAttributes(const DWARFDIE &die);
|
||||
|
||||
lldb::AccessType accessibility = lldb::eAccessNone;
|
||||
bool is_artificial = false;
|
||||
bool is_complete_objc_class = false;
|
||||
bool is_explicit = false;
|
||||
bool is_forward_declaration = false;
|
||||
bool is_inline = false;
|
||||
bool is_scoped_enum = false;
|
||||
bool is_vector = false;
|
||||
bool is_virtual = false;
|
||||
clang::StorageClass storage = clang::SC_None;
|
||||
const char *mangled_name = nullptr;
|
||||
lldb_private::ConstString name;
|
||||
lldb_private::Declaration decl;
|
||||
DWARFDIE object_pointer;
|
||||
DWARFFormValue abstract_origin;
|
||||
DWARFFormValue containing_type;
|
||||
DWARFFormValue signature;
|
||||
DWARFFormValue specification;
|
||||
DWARFFormValue type;
|
||||
lldb::LanguageType class_language = lldb::eLanguageTypeUnknown;
|
||||
llvm::Optional<uint64_t> byte_size;
|
||||
size_t calling_convention = llvm::dwarf::DW_CC_normal;
|
||||
uint32_t bit_stride = 0;
|
||||
uint32_t byte_stride = 0;
|
||||
uint32_t encoding = 0;
|
||||
};
|
||||
|
||||
#endif // SymbolFileDWARF_DWARFASTParserClang_h_
|
||||
|
|
|
@ -3001,8 +3001,7 @@ TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die,
|
|||
if (!dwarf_ast)
|
||||
return {};
|
||||
|
||||
Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
|
||||
TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr);
|
||||
TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr);
|
||||
if (type_sp) {
|
||||
GetTypeList().Insert(type_sp);
|
||||
|
||||
|
|
Loading…
Reference in New Issue