summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp241
1 files changed, 209 insertions, 32 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index caa8c63f8ad..68a0285b69d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -24,11 +24,14 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeMap.h"
#include "lldb/Target/Language.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
@@ -114,6 +117,78 @@ struct BitfieldInfo
}
};
+
+ClangASTImporter &
+DWARFASTParserClang::GetClangASTImporter()
+{
+ if (!m_clang_ast_importer_ap)
+ {
+ m_clang_ast_importer_ap.reset (new ClangASTImporter);
+ }
+ return *m_clang_ast_importer_ap;
+}
+
+
+TypeSP
+DWARFASTParserClang::ParseTypeFromDWO (const DWARFDIE &die, Log *log)
+{
+ ModuleSP dwo_module_sp = die.GetContainingDWOModule();
+ if (dwo_module_sp)
+ {
+ // This type comes from an external DWO module
+ std::vector<CompilerContext> dwo_context;
+ die.GetDWOContext(dwo_context);
+ TypeMap dwo_types;
+ if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true, dwo_types))
+ {
+ const size_t num_dwo_types = dwo_types.GetSize();
+ if (num_dwo_types == 1)
+ {
+ // 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
+ TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
+ if (dwo_type_sp)
+ {
+ lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
+
+ lldb_private::CompilerType type = GetClangASTImporter().CopyType (m_ast, dwo_type);
+
+ //printf ("copied_qual_type: ast = %p, clang_type = %p, name = '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(), external_type->GetName().GetCString());
+ if (type)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ TypeSP type_sp (new Type (die.GetID(),
+ dwarf,
+ dwo_type_sp->GetName(),
+ dwo_type_sp->GetByteSize(),
+ NULL,
+ LLDB_INVALID_UID,
+ Type::eEncodingInvalid,
+ &dwo_type_sp->GetDeclaration(),
+ type,
+ Type::eResolveStateForward));
+
+ dwarf->GetTypeList()->Insert(type_sp);
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
+ if (tag_decl)
+ LinkDeclContextToDIE(tag_decl, die);
+ else
+ {
+ clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ }
+ return type_sp;
+ }
+ }
+ }
+ }
+ }
+ return TypeSP();
+}
+
TypeSP
DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
const DWARFDIE &die,
@@ -487,15 +562,15 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
byte_size_valid ? byte_size : -1,
*unique_ast_entry_ap))
- {
- type_sp = unique_ast_entry_ap->m_type_sp;
- if (type_sp)
{
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- return type_sp;
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ 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);
@@ -600,6 +675,11 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
type_name_cstr);
}
+ // 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);
@@ -833,7 +913,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
case DW_AT_type: encoding_form = form_value; break;
case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break;
+ case DW_AT_declaration: is_forward_declaration = form_value.Boolean(); break;
case DW_AT_allocated:
case DW_AT_associated:
case DW_AT_bit_stride:
@@ -850,6 +930,54 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
}
}
+ if (is_forward_declaration)
+ {
+ type_sp = ParseTypeFromDWO(die, log);
+ if (type_sp)
+ return type_sp;
+
+ DWARFDeclContext die_decl_ctx;
+ die.GetDWARFDeclContext(die_decl_ctx);
+
+ 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),
+ type_name_cstr,
+ 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->DebugInfo()->GetDIE(DIERef(type_sp->GetID())));
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ return type_sp;
+ }
+
+ }
DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
CompilerType enumerator_clang_type;
@@ -1130,7 +1258,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
if (class_type)
{
bool alternate_defn = false;
- if (class_type->GetID() != decl_ctx_die.GetID())
+ if (class_type->GetID() != decl_ctx_die.GetID() || decl_ctx_die.GetContainingDWOModuleDIE())
{
alternate_defn = true;
@@ -1798,6 +1926,33 @@ DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die,
}
bool
+DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type)
+{
+ if (m_clang_ast_importer_ap)
+ return ClangASTContext::CanImport(compiler_type, GetClangASTImporter());
+ else
+ return false;
+}
+
+bool
+DWARFASTParserClang::CompleteType (const lldb_private::CompilerType &compiler_type)
+{
+ if (CanCompleteType(compiler_type))
+ {
+ if (ClangASTContext::Import(compiler_type, GetClangASTImporter()))
+ {
+ ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
+ return true;
+ }
+ else
+ {
+ ClangASTContext::SetHasExternalStorage (compiler_type.GetOpaqueQualType(), false);
+ }
+ }
+ return false;
+}
+
+bool
DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
lldb_private::Type *type,
CompilerType &clang_type)
@@ -1868,25 +2023,17 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
DWARFDIECollection member_function_dies;
DelayedPropertyList delayed_properties;
- if (!ParseChildMembers (sc,
- die,
- clang_type,
- class_language,
- base_classes,
- member_accessibilities,
- member_function_dies,
- delayed_properties,
- default_accessibility,
- is_a_class,
- layout_info))
- {
- auto module = dwarf->GetObjectFile()->GetModule();
- module->ReportError (":: Class %s has members with incomplete type.", die.GetName());
- if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
- module->ReportError(":: Try compiling the source file with -fno-limit-debug-info.");
-
- return false;
- }
+ ParseChildMembers (sc,
+ die,
+ clang_type,
+ class_language,
+ base_classes,
+ member_accessibilities,
+ member_function_dies,
+ delayed_properties,
+ default_accessibility,
+ is_a_class,
+ layout_info);
// Now parse any methods if there were any...
size_t num_functions = member_function_dies.Size();
@@ -1977,7 +2124,14 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
module->ReportError (":: Try compiling the source file with -fno-limit-debug-info.");
- return false;
+ // We have no choice other than to pretend that the base class
+ // is complete. If we don't do this, clang will crash when we
+ // call setBases() inside of "clang_type.SetBaseClassesForClassType()"
+ // below. Since we provide layout assistance, all ivars in this
+ // class and other classes will be fine, this is the best we can do
+ // short of crashing.
+ ClangASTContext::StartTagDeclarationDefinition (base_class_type);
+ ClangASTContext::CompleteTagDeclarationDefinition (base_class_type);
}
}
}
@@ -2420,7 +2574,6 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
if (!parent_die)
return 0;
- uint32_t incomplete_member_info_count = 0;
uint32_t member_idx = 0;
BitfieldInfo last_field_info;
@@ -2754,8 +2907,8 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
}
CompilerType member_clang_type = member_type->GetLayoutCompilerType ();
- if (!member_clang_type.IsCompleteType() && !member_clang_type.GetCompleteType())
- incomplete_member_info_count += 1;
+ if (!member_clang_type.IsCompleteType())
+ member_clang_type.GetCompleteType();
{
// Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>).
@@ -2789,6 +2942,30 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
}
}
+ if (ClangASTContext::IsCXXClassType(member_clang_type) && member_clang_type.GetCompleteType() == false)
+ {
+ if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
+ module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nTry compiling the source file with -fno-limit-debug-info",
+ parent_die.GetOffset(),
+ parent_die.GetName(),
+ die.GetOffset(),
+ name);
+ else
+ module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s",
+ parent_die.GetOffset(),
+ parent_die.GetName(),
+ die.GetOffset(),
+ name,
+ sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file");
+ // We have no choice other than to pretend that the member class
+ // is complete. If we don't do this, clang will crash when trying
+ // to layout the class. Since we provide layout assistance, all
+ // ivars in this class and other classes will be fine, this is
+ // the best we can do short of crashing.
+ ClangASTContext::StartTagDeclarationDefinition(member_clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type);
+ }
+
field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type,
name,
member_clang_type,
@@ -2978,7 +3155,7 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
}
}
- return incomplete_member_info_count == 0;
+ return true;
}
OpenPOWER on IntegriCloud