forked from OSchip/llvm-project
Added support for -gmodule debugging when debug info is left in the .o files on Darwin.
This is done by finding the types that are forward declarations that come from a module, and loading that module's debug info in a separate lldb_private::Module, and copying the type over into the current module using a ClangASTImporter object. ClangASTImporter objects are already used to copy types from on clang::ASTContext to another for expressions so the type copying code has been around for a while. A new FindTypes variant was added to SymbolVendor and SymbolFile: size_t SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types); size_t SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types); The CompilerContext is a way to represent the exact context of a type and pass it through an agnostic API boundary so that we can find that exact context elsewhere in another file. This was required here because we can have a module that has submodules, both of which have a "foo" type. I am not able to add tests for this yet as we currently don't build our C/C++/ObjC binaries with the clang binary that we build. There are some driver issues where it can't find the header files for the C and C++ standard library which makes compiling these tests hard. We can't also guarantee that if we are building with clang that it supporst the exact format of -gmodule debugging that we are trying to test. We have had other versions of clang that had a different implementation of -gmodule debugging that we are no longer supporting, so we can't enable tests if we are building with clang without compiling something and looking at the structure of the DWARF that was generated to ensure that it is the format we can actually use. llvm-svn: 254476
This commit is contained in:
parent
f3be9d5c0b
commit
5dfc4a4d02
lldb
include/lldb
Symbol
ClangASTContext.hClangASTImporter.hClangExternalASTSourceCallbacks.hSymbolFile.hSymbolVendor.hType.h
lldb-forward.hlldb-private-enumerations.hpackages/Python/lldbsuite/test/lang/cpp/incomplete-types
source
|
@ -1006,10 +1006,18 @@ public:
|
|||
lldb::AccessType access,
|
||||
bool is_artificial);
|
||||
|
||||
bool
|
||||
static bool
|
||||
SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern);
|
||||
|
||||
|
||||
|
||||
static bool
|
||||
CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer);
|
||||
|
||||
static bool
|
||||
Import (const CompilerType &type, lldb_private::ClangASTImporter &importer);
|
||||
|
||||
static bool
|
||||
GetHasExternalStorage (const CompilerType &type);
|
||||
//------------------------------------------------------------------
|
||||
// Tag Declarations
|
||||
//------------------------------------------------------------------
|
||||
|
@ -1092,13 +1100,19 @@ public:
|
|||
|
||||
void
|
||||
DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) override;
|
||||
|
||||
|
||||
static void
|
||||
DumpTypeName (const CompilerType &type);
|
||||
|
||||
static clang::EnumDecl *
|
||||
GetAsEnumDecl (const CompilerType& type);
|
||||
|
||||
static clang::RecordDecl *
|
||||
GetAsRecordDecl (const CompilerType& type);
|
||||
|
||||
|
||||
static clang::TagDecl *
|
||||
GetAsTagDecl (const CompilerType& type);
|
||||
|
||||
clang::CXXRecordDecl *
|
||||
GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type);
|
||||
|
||||
|
@ -1109,9 +1123,12 @@ public:
|
|||
GetQualType (const CompilerType& type)
|
||||
{
|
||||
// Make sure we have a clang type before making a clang::QualType
|
||||
ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
|
||||
if (ast)
|
||||
return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType());
|
||||
if (type.GetOpaqueQualType())
|
||||
{
|
||||
ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
|
||||
if (ast)
|
||||
return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType());
|
||||
}
|
||||
return clang::QualType();
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,11 @@ public:
|
|||
CopyType (clang::ASTContext *dst_ctx,
|
||||
clang::ASTContext *src_ctx,
|
||||
lldb::opaque_compiler_type_t type);
|
||||
|
||||
|
||||
CompilerType
|
||||
CopyType (ClangASTContext &dst,
|
||||
const CompilerType &src_type);
|
||||
|
||||
clang::Decl *
|
||||
CopyDecl (clang::ASTContext *dst_ctx,
|
||||
clang::ASTContext *src_ctx,
|
||||
|
@ -134,7 +138,10 @@ public:
|
|||
|
||||
bool
|
||||
CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
|
||||
|
||||
|
||||
bool
|
||||
CompleteAndFetchChildren (clang::QualType type);
|
||||
|
||||
bool
|
||||
RequireCompleteType (clang::QualType type);
|
||||
|
||||
|
|
|
@ -97,6 +97,11 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
FindExternalLexicalDecls(const clang::DeclContext *DC,
|
||||
llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
|
||||
llvm::SmallVectorImpl<clang::Decl *> &Result) override;
|
||||
|
||||
bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName decl_name) override;
|
||||
|
||||
void CompleteType(clang::TagDecl *tag_decl) override;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "lldb/Symbol/CompilerType.h"
|
||||
#include "lldb/Symbol/CompilerDecl.h"
|
||||
#include "lldb/Symbol/CompilerDeclContext.h"
|
||||
|
||||
#include "lldb/Symbol/Type.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -142,6 +141,8 @@ public:
|
|||
virtual uint32_t FindFunctions (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list);
|
||||
virtual uint32_t FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list);
|
||||
virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, TypeMap& types);
|
||||
virtual size_t FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
|
||||
|
||||
// virtual uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0;
|
||||
virtual TypeList * GetTypeList ();
|
||||
virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
|
||||
|
|
|
@ -128,6 +128,9 @@ public:
|
|||
size_t max_matches,
|
||||
TypeMap& types);
|
||||
|
||||
virtual size_t
|
||||
FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
|
||||
|
||||
virtual CompilerDeclContext
|
||||
FindNamespace (const SymbolContext& sc,
|
||||
const ConstString &name,
|
||||
|
|
|
@ -24,6 +24,31 @@
|
|||
|
||||
namespace lldb_private {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// CompilerContext allows an array of these items to be passed to
|
||||
// perform detailed lookups in SymbolVendor and SymbolFile functions.
|
||||
//----------------------------------------------------------------------
|
||||
struct CompilerContext
|
||||
{
|
||||
CompilerContext (CompilerContextKind t, const ConstString &n) :
|
||||
type(t),
|
||||
name(n)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator == (const CompilerContext &rhs) const
|
||||
{
|
||||
return type == rhs.type && name == rhs.name;
|
||||
}
|
||||
|
||||
void
|
||||
Dump () const;
|
||||
|
||||
CompilerContextKind type;
|
||||
ConstString name;
|
||||
};
|
||||
|
||||
class SymbolFileType :
|
||||
public std::enable_shared_from_this<SymbolFileType>,
|
||||
public UserID
|
||||
|
@ -35,6 +60,9 @@ class SymbolFileType :
|
|||
{
|
||||
}
|
||||
|
||||
SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp);
|
||||
|
||||
|
||||
~SymbolFileType ()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ class CommandObject;
|
|||
class CommandReturnObject;
|
||||
class Communication;
|
||||
class CompactUnwindInfo;
|
||||
struct CompilerContext;
|
||||
class CompilerDecl;
|
||||
class CompilerDeclContext;
|
||||
class CompilerType;
|
||||
|
|
|
@ -241,6 +241,25 @@ enum class TypeValidatorResult : bool {
|
|||
Success = true,
|
||||
Failure = false
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Enumerations that can be used to specify scopes types when looking up
|
||||
// types.
|
||||
//----------------------------------------------------------------------
|
||||
enum class CompilerContextKind
|
||||
{
|
||||
Invalid = 0,
|
||||
TranslationUnit,
|
||||
Module,
|
||||
Namespace,
|
||||
Class,
|
||||
Structure,
|
||||
Union,
|
||||
Function,
|
||||
Variable,
|
||||
Enumeration,
|
||||
Typedef
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
|
|
|
@ -14,11 +14,11 @@ class TestCppIncompleteTypes(TestBase):
|
|||
|
||||
value_f = frame.EvaluateExpression("f")
|
||||
self.assertTrue(value_f.IsValid(), "'expr f' results in a valid SBValue object")
|
||||
self.assertFalse(value_f.GetError().Success(), "'expr f' results in an error, but LLDB does not crash")
|
||||
self.assertTrue(value_f.GetError().Success(), "'expr f' is successful")
|
||||
|
||||
value_a = frame.EvaluateExpression("a")
|
||||
self.assertTrue(value_a.IsValid(), "'expr a' results in a valid SBValue object")
|
||||
self.assertFalse(value_a.GetError().Success(), "'expr a' results in an error, but LLDB does not crash")
|
||||
self.assertTrue(value_a.GetError().Success(), "'expr a' is successful")
|
||||
|
||||
@skipIfGcc
|
||||
@skipIfWindows # Clang on Windows asserts in external record layout in this case.
|
||||
|
|
|
@ -32,6 +32,18 @@ public:
|
|||
ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
|
||||
const DWARFDIE &die) = 0;
|
||||
|
||||
virtual bool
|
||||
CanCompleteType (const lldb_private::CompilerType &compiler_type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
CompleteType (const lldb_private::CompilerType &compiler_type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
CompleteTypeFromDWARF (const DWARFDIE &die,
|
||||
lldb_private::Type *type,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -1797,6 +1925,33 @@ DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die,
|
|||
return template_param_infos.args.size() == template_param_infos.names.size();
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,12 @@ public:
|
|||
ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
|
||||
const DWARFDIE &die) override;
|
||||
|
||||
bool
|
||||
CanCompleteType (const lldb_private::CompilerType &compiler_type) override;
|
||||
|
||||
bool
|
||||
CompleteType (const lldb_private::CompilerType &compiler_type) override;
|
||||
|
||||
bool
|
||||
CompleteTypeFromDWARF (const DWARFDIE &die,
|
||||
lldb_private::Type *type,
|
||||
|
@ -175,6 +181,19 @@ protected:
|
|||
void
|
||||
LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die);
|
||||
|
||||
lldb_private::ClangASTImporter &
|
||||
GetClangASTImporter();
|
||||
|
||||
lldb::TypeSP
|
||||
ParseTypeFromDWO (const 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);
|
||||
|
||||
typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
|
||||
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
|
||||
//typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
|
||||
|
@ -188,6 +207,7 @@ protected:
|
|||
DIEToDeclContextMap m_die_to_decl_ctx;
|
||||
DeclContextToDIEMap m_decl_ctx_to_die;
|
||||
RecordDeclToLayoutMap m_record_decl_to_layout_map;
|
||||
std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap;
|
||||
};
|
||||
|
||||
#endif // SymbolFileDWARF_DWARFASTParserClang_h_
|
||||
|
|
|
@ -22,8 +22,11 @@
|
|||
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
#include "lldb/Symbol/TypeSystem.h"
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
DIERef
|
||||
DWARFDIE::GetDIERef() const
|
||||
{
|
||||
|
@ -307,6 +310,51 @@ DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const
|
||||
{
|
||||
const dw_tag_t tag = Tag();
|
||||
if (tag == DW_TAG_compile_unit)
|
||||
return;
|
||||
DWARFDIE parent = GetParent();
|
||||
if (parent)
|
||||
parent.GetDWOContext(context);
|
||||
switch (tag)
|
||||
{
|
||||
case DW_TAG_module:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName())));
|
||||
break;
|
||||
case DW_TAG_namespace:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName())));
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName())));
|
||||
break;
|
||||
case DW_TAG_union_type:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName())));
|
||||
break;
|
||||
case DW_TAG_class_type:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName())));
|
||||
break;
|
||||
case DW_TAG_enumeration_type:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName())));
|
||||
break;
|
||||
case DW_TAG_subprogram:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname())));
|
||||
break;
|
||||
case DW_TAG_variable:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname())));
|
||||
break;
|
||||
case DW_TAG_typedef:
|
||||
context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName())));
|
||||
break;
|
||||
default:
|
||||
assert(!"remove this prior to checkin");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DWARFDIE
|
||||
DWARFDIE::GetParentDeclContextDIE () const
|
||||
|
@ -371,6 +419,45 @@ DWARFDIE::IsStructOrClass () const
|
|||
return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
|
||||
}
|
||||
|
||||
|
||||
DWARFDIE
|
||||
DWARFDIE::GetContainingDWOModuleDIE () const
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
DWARFDIE top_module_die;
|
||||
// Now make sure this DIE is scoped in a DW_TAG_module tag and return true if so
|
||||
for (DWARFDIE parent = GetParent(); parent.IsValid(); parent = parent.GetParent())
|
||||
{
|
||||
const dw_tag_t tag = parent.Tag();
|
||||
if (tag == DW_TAG_module)
|
||||
top_module_die = parent;
|
||||
else if (tag == DW_TAG_compile_unit)
|
||||
break;
|
||||
}
|
||||
|
||||
return top_module_die;
|
||||
}
|
||||
return DWARFDIE();
|
||||
}
|
||||
|
||||
lldb::ModuleSP
|
||||
DWARFDIE::GetContainingDWOModule () const
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
|
||||
|
||||
if (dwo_module_die)
|
||||
{
|
||||
const char *module_name = dwo_module_die.GetName();
|
||||
if (module_name)
|
||||
return GetDWARF()->GetDWOModule (lldb_private::ConstString(module_name));
|
||||
}
|
||||
}
|
||||
return lldb::ModuleSP();
|
||||
}
|
||||
|
||||
bool
|
||||
DWARFDIE::HasChildren () const
|
||||
{
|
||||
|
|
|
@ -126,6 +126,12 @@ public:
|
|||
m_die = nullptr;
|
||||
}
|
||||
|
||||
lldb::ModuleSP
|
||||
GetContainingDWOModule () const;
|
||||
|
||||
DWARFDIE
|
||||
GetContainingDWOModuleDIE () const;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Accessing information about a DIE
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -217,6 +223,9 @@ public:
|
|||
void
|
||||
GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const;
|
||||
|
||||
void
|
||||
GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Getting attribute values from the DIE.
|
||||
//
|
||||
|
|
|
@ -1077,9 +1077,9 @@ SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, st
|
|||
if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage()))
|
||||
{
|
||||
UpdateExternalModuleListIfNeeded();
|
||||
for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules)
|
||||
for (const auto &pair : m_external_type_modules)
|
||||
{
|
||||
imported_modules.push_back(external_type_module.second.m_name);
|
||||
imported_modules.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1515,13 +1515,32 @@ bool
|
|||
SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type)
|
||||
{
|
||||
CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
|
||||
return GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType());
|
||||
if (GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
TypeSystem *type_system = compiler_type.GetTypeSystem();
|
||||
if (type_system)
|
||||
{
|
||||
DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
|
||||
if (dwarf_ast)
|
||||
return dwarf_ast->CanCompleteType(compiler_type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SymbolFileDWARF::CompleteType (CompilerType &compiler_type)
|
||||
{
|
||||
TypeSystem *type_system = compiler_type.GetTypeSystem();
|
||||
if (type_system)
|
||||
{
|
||||
DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
|
||||
if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type))
|
||||
return dwarf_ast->CompleteType(compiler_type);
|
||||
}
|
||||
|
||||
// We have a struct/union/class/enum that needs to be fully resolved.
|
||||
CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
|
||||
auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType());
|
||||
|
@ -1641,6 +1660,17 @@ SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc)
|
|||
return false;
|
||||
}
|
||||
|
||||
lldb::ModuleSP
|
||||
SymbolFileDWARF::GetDWOModule (ConstString name)
|
||||
{
|
||||
UpdateExternalModuleListIfNeeded();
|
||||
const auto &pos = m_external_type_modules.find(name);
|
||||
if (pos != m_external_type_modules.end())
|
||||
return pos->second;
|
||||
else
|
||||
return lldb::ModuleSP();
|
||||
}
|
||||
|
||||
void
|
||||
SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
|
||||
{
|
||||
|
@ -1658,37 +1688,24 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
|
|||
const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
|
||||
if (die && die.HasChildren() == false)
|
||||
{
|
||||
const uint64_t name_strp = die.GetAttributeValueAsUnsigned (DW_AT_name, UINT64_MAX);
|
||||
const uint64_t dwo_path_strp = die.GetAttributeValueAsUnsigned (DW_AT_GNU_dwo_name, UINT64_MAX);
|
||||
|
||||
if (name_strp != UINT64_MAX)
|
||||
const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
|
||||
|
||||
if (name)
|
||||
{
|
||||
if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end())
|
||||
ConstString const_name(name);
|
||||
if (m_external_type_modules.find(const_name) == m_external_type_modules.end())
|
||||
{
|
||||
const char *name = get_debug_str_data().PeekCStr(name_strp);
|
||||
const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp);
|
||||
if (name || dwo_path)
|
||||
ModuleSP module_sp;
|
||||
const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
|
||||
if (dwo_path)
|
||||
{
|
||||
ModuleSP module_sp;
|
||||
if (dwo_path)
|
||||
{
|
||||
ModuleSpec dwo_module_spec;
|
||||
dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
|
||||
dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
|
||||
//printf ("Loading dwo = '%s'\n", dwo_path);
|
||||
Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (dwo_path_strp != LLDB_INVALID_UID)
|
||||
{
|
||||
m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp };
|
||||
}
|
||||
else
|
||||
{
|
||||
// This hack should be removed promptly once clang emits both.
|
||||
m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp };
|
||||
}
|
||||
ModuleSpec dwo_module_spec;
|
||||
dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
|
||||
dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
|
||||
//printf ("Loading dwo = '%s'\n", dwo_path);
|
||||
Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
|
||||
}
|
||||
m_external_type_modules[const_name] = module_sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2970,6 +2987,104 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
|
|||
}
|
||||
return num_matches;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateExternalModuleListIfNeeded();
|
||||
|
||||
for (const auto &pair : m_external_type_modules)
|
||||
{
|
||||
ModuleSP external_module_sp = pair.second;
|
||||
if (external_module_sp)
|
||||
{
|
||||
SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor();
|
||||
if (sym_vendor)
|
||||
{
|
||||
const uint32_t num_external_matches = sym_vendor->FindTypes (sc,
|
||||
name,
|
||||
parent_decl_ctx,
|
||||
append,
|
||||
max_matches,
|
||||
types);
|
||||
if (num_external_matches)
|
||||
return num_external_matches;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
SymbolFileDWARF::FindTypes (const std::vector<CompilerContext> &context,
|
||||
bool append,
|
||||
TypeMap& types)
|
||||
{
|
||||
if (!append)
|
||||
types.Clear();
|
||||
|
||||
if (context.empty())
|
||||
return 0;
|
||||
|
||||
DIEArray die_offsets;
|
||||
|
||||
ConstString name = context.back().name;
|
||||
|
||||
if (m_using_apple_tables)
|
||||
{
|
||||
if (m_apple_types_ap.get())
|
||||
{
|
||||
const char *name_cstr = name.GetCString();
|
||||
m_apple_types_ap->FindByName (name_cstr, die_offsets);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_indexed)
|
||||
Index ();
|
||||
|
||||
m_type_index.Find (name, die_offsets);
|
||||
}
|
||||
|
||||
const size_t num_die_matches = die_offsets.size();
|
||||
|
||||
if (num_die_matches)
|
||||
{
|
||||
size_t num_matches = 0;
|
||||
DWARFDebugInfo* debug_info = DebugInfo();
|
||||
for (size_t i=0; i<num_die_matches; ++i)
|
||||
{
|
||||
const DIERef& die_ref = die_offsets[i];
|
||||
DWARFDIE die = debug_info->GetDIE (die_ref);
|
||||
|
||||
if (die)
|
||||
{
|
||||
std::vector<CompilerContext> die_context;
|
||||
die.GetDWOContext(die_context);
|
||||
if (die_context != context)
|
||||
continue;
|
||||
|
||||
Type *matching_type = ResolveType (die, true, true);
|
||||
if (matching_type)
|
||||
{
|
||||
// We found a type pointer, now find the shared pointer form our type list
|
||||
types.InsertUnique (matching_type->shared_from_this());
|
||||
++num_matches;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_using_apple_tables)
|
||||
{
|
||||
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
|
||||
die_ref.die_offset, name.GetCString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return num_matches;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,6 +211,11 @@ public:
|
|||
uint32_t max_matches,
|
||||
lldb_private::TypeMap& types) override;
|
||||
|
||||
size_t
|
||||
FindTypes (const std::vector<lldb_private::CompilerContext> &context,
|
||||
bool append,
|
||||
lldb_private::TypeMap& types) override;
|
||||
|
||||
lldb_private::TypeList *
|
||||
GetTypeList () override;
|
||||
|
||||
|
@ -306,6 +311,9 @@ public:
|
|||
virtual lldb_private::DWARFExpression::LocationListFormat
|
||||
GetLocationListFormat() const;
|
||||
|
||||
lldb::ModuleSP
|
||||
GetDWOModule (lldb_private::ConstString name);
|
||||
|
||||
protected:
|
||||
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
|
||||
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
|
||||
|
@ -483,12 +491,7 @@ protected:
|
|||
|
||||
typedef std::set<lldb_private::Type *> TypeSet;
|
||||
|
||||
typedef struct {
|
||||
lldb_private::ConstString m_name;
|
||||
lldb::ModuleSP m_module_sp;
|
||||
} ClangModuleInfo;
|
||||
|
||||
typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap;
|
||||
typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap;
|
||||
|
||||
void
|
||||
GetTypes (const DWARFDIE &die,
|
||||
|
|
|
@ -2297,9 +2297,6 @@ ClangASTContext::GetCompleteDecl (clang::ASTContext *ast,
|
|||
if (tag_decl->isCompleteDefinition())
|
||||
return true;
|
||||
|
||||
if (!tag_decl->hasExternalLexicalStorage())
|
||||
return false;
|
||||
|
||||
ast_source->CompleteType(tag_decl);
|
||||
|
||||
return !tag_decl->getTypeForDecl()->isIncompleteType();
|
||||
|
@ -2451,81 +2448,110 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool all
|
|||
case clang::Type::ConstantArray:
|
||||
case clang::Type::IncompleteArray:
|
||||
case clang::Type::VariableArray:
|
||||
{
|
||||
const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
|
||||
|
||||
if (array_type)
|
||||
return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
|
||||
}
|
||||
{
|
||||
const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
|
||||
|
||||
if (array_type)
|
||||
return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Record:
|
||||
case clang::Type::Enum:
|
||||
{
|
||||
const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
|
||||
if (tag_type)
|
||||
{
|
||||
clang::TagDecl *tag_decl = tag_type->getDecl();
|
||||
if (tag_decl)
|
||||
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
if (cxx_record_decl)
|
||||
{
|
||||
if (tag_decl->isCompleteDefinition())
|
||||
bool fields_loaded = cxx_record_decl->hasLoadedFieldsFromExternalStorage();
|
||||
if (cxx_record_decl->isCompleteDefinition() && fields_loaded)
|
||||
return true;
|
||||
|
||||
|
||||
if (!allow_completion)
|
||||
return false;
|
||||
|
||||
if (tag_decl->hasExternalLexicalStorage())
|
||||
|
||||
// Call the field_begin() accessor to for it to use the external source
|
||||
// to load the fields...
|
||||
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
|
||||
if (external_ast_source)
|
||||
{
|
||||
if (ast)
|
||||
external_ast_source->CompleteType(cxx_record_decl);
|
||||
if (cxx_record_decl->isCompleteDefinition())
|
||||
{
|
||||
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
|
||||
if (external_ast_source)
|
||||
{
|
||||
external_ast_source->CompleteType(tag_decl);
|
||||
return !tag_type->isIncompleteType();
|
||||
}
|
||||
cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true);
|
||||
cxx_record_decl->field_begin();
|
||||
return cxx_record_decl->hasLoadedFieldsFromExternalStorage();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Enum:
|
||||
{
|
||||
const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
|
||||
if (tag_type)
|
||||
{
|
||||
clang::TagDecl *tag_decl = tag_type->getDecl();
|
||||
if (tag_decl)
|
||||
{
|
||||
if (tag_decl->getDefinition())
|
||||
return true;
|
||||
|
||||
if (!allow_completion)
|
||||
return false;
|
||||
|
||||
if (tag_decl->hasExternalLexicalStorage())
|
||||
{
|
||||
if (ast)
|
||||
{
|
||||
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
|
||||
if (external_ast_source)
|
||||
{
|
||||
external_ast_source->CompleteType(tag_decl);
|
||||
return !tag_type->isIncompleteType();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::ObjCObject:
|
||||
case clang::Type::ObjCInterface:
|
||||
{
|
||||
const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
|
||||
if (objc_class_type)
|
||||
{
|
||||
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
// We currently can't complete objective C types through the newly added ASTContext
|
||||
// because it only supports TagDecl objects right now...
|
||||
if (class_interface_decl)
|
||||
const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
|
||||
if (objc_class_type)
|
||||
{
|
||||
if (class_interface_decl->getDefinition())
|
||||
return true;
|
||||
|
||||
if (!allow_completion)
|
||||
return false;
|
||||
|
||||
if (class_interface_decl->hasExternalLexicalStorage())
|
||||
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
// We currently can't complete objective C types through the newly added ASTContext
|
||||
// because it only supports TagDecl objects right now...
|
||||
if (class_interface_decl)
|
||||
{
|
||||
if (ast)
|
||||
if (class_interface_decl->getDefinition())
|
||||
return true;
|
||||
|
||||
if (!allow_completion)
|
||||
return false;
|
||||
|
||||
if (class_interface_decl->hasExternalLexicalStorage())
|
||||
{
|
||||
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
|
||||
if (external_ast_source)
|
||||
if (ast)
|
||||
{
|
||||
external_ast_source->CompleteType (class_interface_decl);
|
||||
return !objc_class_type->isIncompleteType();
|
||||
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
|
||||
if (external_ast_source)
|
||||
{
|
||||
external_ast_source->CompleteType (class_interface_decl);
|
||||
return !objc_class_type->isIncompleteType();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Typedef:
|
||||
|
@ -2536,7 +2562,10 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool all
|
|||
|
||||
case clang::Type::Paren:
|
||||
return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion);
|
||||
|
||||
|
||||
case clang::Type::Attributed:
|
||||
return GetCompleteQualType (ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(), allow_completion);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -7160,6 +7189,16 @@ ClangASTContext::GetAsRecordDecl (const CompilerType& type)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
clang::TagDecl *
|
||||
ClangASTContext::GetAsTagDecl (const CompilerType& type)
|
||||
{
|
||||
clang::QualType qual_type = GetCanonicalQualType(type);
|
||||
if (qual_type.isNull())
|
||||
return nullptr;
|
||||
else
|
||||
return qual_type->getAsTagDecl();
|
||||
}
|
||||
|
||||
clang::CXXRecordDecl *
|
||||
ClangASTContext::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type)
|
||||
{
|
||||
|
@ -8036,6 +8075,64 @@ ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type,
|
|||
return objc_method_decl;
|
||||
}
|
||||
|
||||
bool
|
||||
ClangASTContext::GetHasExternalStorage (const CompilerType &type)
|
||||
{
|
||||
if (IsClangType(type))
|
||||
return false;
|
||||
|
||||
clang::QualType qual_type (GetCanonicalQualType(type));
|
||||
|
||||
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
|
||||
switch (type_class)
|
||||
{
|
||||
case clang::Type::Record:
|
||||
{
|
||||
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
if (cxx_record_decl)
|
||||
return cxx_record_decl->hasExternalLexicalStorage () || cxx_record_decl->hasExternalVisibleStorage();
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Enum:
|
||||
{
|
||||
clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
|
||||
if (enum_decl)
|
||||
return enum_decl->hasExternalLexicalStorage () || enum_decl->hasExternalVisibleStorage();
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::ObjCObject:
|
||||
case clang::Type::ObjCInterface:
|
||||
{
|
||||
const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
|
||||
assert (objc_class_type);
|
||||
if (objc_class_type)
|
||||
{
|
||||
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
|
||||
if (class_interface_decl)
|
||||
return class_interface_decl->hasExternalLexicalStorage () || class_interface_decl->hasExternalVisibleStorage ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Typedef:
|
||||
return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()));
|
||||
|
||||
case clang::Type::Elaborated:
|
||||
return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
|
||||
|
||||
case clang::Type::Paren:
|
||||
return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern)
|
||||
{
|
||||
|
@ -8106,38 +8203,173 @@ ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
ClangASTContext::CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer)
|
||||
{
|
||||
if (IsClangType(type))
|
||||
{
|
||||
// TODO: remove external completion BOOL
|
||||
// CompleteAndFetchChildren should get the Decl out and check for the
|
||||
|
||||
clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
|
||||
|
||||
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
|
||||
switch (type_class)
|
||||
{
|
||||
case clang::Type::Record:
|
||||
{
|
||||
const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
if (cxx_record_decl)
|
||||
{
|
||||
if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Enum:
|
||||
{
|
||||
clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
|
||||
if (enum_decl)
|
||||
{
|
||||
if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::ObjCObject:
|
||||
case clang::Type::ObjCInterface:
|
||||
{
|
||||
const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
|
||||
if (objc_class_type)
|
||||
{
|
||||
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
// We currently can't complete objective C types through the newly added ASTContext
|
||||
// because it only supports TagDecl objects right now...
|
||||
if (class_interface_decl)
|
||||
{
|
||||
if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case clang::Type::Typedef:
|
||||
return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer);
|
||||
|
||||
case clang::Type::Elaborated:
|
||||
return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer);
|
||||
|
||||
case clang::Type::Paren:
|
||||
return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
ClangASTContext::Import (const CompilerType &type, lldb_private::ClangASTImporter &importer)
|
||||
{
|
||||
if (IsClangType(type))
|
||||
{
|
||||
// TODO: remove external completion BOOL
|
||||
// CompleteAndFetchChildren should get the Decl out and check for the
|
||||
|
||||
clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
|
||||
|
||||
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
|
||||
switch (type_class)
|
||||
{
|
||||
case clang::Type::Record:
|
||||
{
|
||||
const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
if (cxx_record_decl)
|
||||
{
|
||||
if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL))
|
||||
return importer.CompleteAndFetchChildren(qual_type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Enum:
|
||||
{
|
||||
clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
|
||||
if (enum_decl)
|
||||
{
|
||||
if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL))
|
||||
return importer.CompleteAndFetchChildren(qual_type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::ObjCObject:
|
||||
case clang::Type::ObjCInterface:
|
||||
{
|
||||
const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
|
||||
if (objc_class_type)
|
||||
{
|
||||
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
// We currently can't complete objective C types through the newly added ASTContext
|
||||
// because it only supports TagDecl objects right now...
|
||||
if (class_interface_decl)
|
||||
{
|
||||
if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL))
|
||||
return importer.CompleteAndFetchChildren(qual_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case clang::Type::Typedef:
|
||||
return Import (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer);
|
||||
|
||||
case clang::Type::Elaborated:
|
||||
return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer);
|
||||
|
||||
case clang::Type::Paren:
|
||||
return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark TagDecl
|
||||
|
||||
bool
|
||||
ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
|
||||
{
|
||||
if (type)
|
||||
clang::QualType qual_type (ClangASTContext::GetQualType(type));
|
||||
if (!qual_type.isNull())
|
||||
{
|
||||
|
||||
clang::QualType qual_type (GetQualType(type));
|
||||
const clang::Type *t = qual_type.getTypePtr();
|
||||
if (t)
|
||||
const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
|
||||
if (tag_type)
|
||||
{
|
||||
const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(t);
|
||||
if (tag_type)
|
||||
clang::TagDecl *tag_decl = tag_type->getDecl();
|
||||
if (tag_decl)
|
||||
{
|
||||
clang::TagDecl *tag_decl = tag_type->getDecl();
|
||||
if (tag_decl)
|
||||
{
|
||||
tag_decl->startDefinition();
|
||||
return true;
|
||||
}
|
||||
tag_decl->startDefinition();
|
||||
return true;
|
||||
}
|
||||
|
||||
const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(t);
|
||||
if (object_type)
|
||||
}
|
||||
|
||||
const clang::ObjCObjectType *object_type = qual_type->getAs<clang::ObjCObjectType>();
|
||||
if (object_type)
|
||||
{
|
||||
clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
|
||||
if (interface_decl)
|
||||
{
|
||||
clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
|
||||
if (interface_decl)
|
||||
{
|
||||
interface_decl->startDefinition();
|
||||
return true;
|
||||
}
|
||||
interface_decl->startDefinition();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8147,26 +8379,22 @@ ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
|
|||
bool
|
||||
ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type)
|
||||
{
|
||||
if (type)
|
||||
clang::QualType qual_type (ClangASTContext::GetQualType(type));
|
||||
if (!qual_type.isNull())
|
||||
{
|
||||
clang::QualType qual_type (GetQualType(type));
|
||||
if (qual_type.isNull())
|
||||
return false;
|
||||
ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
|
||||
if (lldb_ast == nullptr)
|
||||
return false;
|
||||
clang::ASTContext *ast = lldb_ast->getASTContext();
|
||||
|
||||
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
|
||||
if (cxx_record_decl)
|
||||
{
|
||||
cxx_record_decl->completeDefinition();
|
||||
|
||||
if (!cxx_record_decl->isCompleteDefinition())
|
||||
cxx_record_decl->completeDefinition();
|
||||
cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
|
||||
cxx_record_decl->setHasExternalLexicalStorage (false);
|
||||
cxx_record_decl->setHasExternalVisibleStorage (false);
|
||||
return true;
|
||||
}
|
||||
|
||||
const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(qual_type.getTypePtr());
|
||||
const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
|
||||
|
||||
if (enutype)
|
||||
{
|
||||
|
@ -8174,25 +8402,33 @@ ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type)
|
|||
|
||||
if (enum_decl)
|
||||
{
|
||||
/// TODO This really needs to be fixed.
|
||||
|
||||
unsigned NumPositiveBits = 1;
|
||||
unsigned NumNegativeBits = 0;
|
||||
|
||||
clang::QualType promotion_qual_type;
|
||||
// If the enum integer type is less than an integer in bit width,
|
||||
// then we must promote it to an integer size.
|
||||
if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy))
|
||||
if (!enum_decl->isCompleteDefinition())
|
||||
{
|
||||
if (enum_decl->getIntegerType()->isSignedIntegerType())
|
||||
promotion_qual_type = ast->IntTy;
|
||||
ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
|
||||
if (lldb_ast == nullptr)
|
||||
return false;
|
||||
clang::ASTContext *ast = lldb_ast->getASTContext();
|
||||
|
||||
/// TODO This really needs to be fixed.
|
||||
|
||||
unsigned NumPositiveBits = 1;
|
||||
unsigned NumNegativeBits = 0;
|
||||
|
||||
clang::QualType promotion_qual_type;
|
||||
// If the enum integer type is less than an integer in bit width,
|
||||
// then we must promote it to an integer size.
|
||||
if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy))
|
||||
{
|
||||
if (enum_decl->getIntegerType()->isSignedIntegerType())
|
||||
promotion_qual_type = ast->IntTy;
|
||||
else
|
||||
promotion_qual_type = ast->UnsignedIntTy;
|
||||
}
|
||||
else
|
||||
promotion_qual_type = ast->UnsignedIntTy;
|
||||
promotion_qual_type = enum_decl->getIntegerType();
|
||||
|
||||
enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits);
|
||||
}
|
||||
else
|
||||
promotion_qual_type = enum_decl->getIntegerType();
|
||||
|
||||
enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -8976,6 +9212,72 @@ ClangASTContext::DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClangASTContext::DumpTypeName (const CompilerType &type)
|
||||
{
|
||||
if (IsClangType(type))
|
||||
{
|
||||
clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
|
||||
|
||||
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
|
||||
switch (type_class)
|
||||
{
|
||||
case clang::Type::Record:
|
||||
{
|
||||
const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
if (cxx_record_decl)
|
||||
printf("class %s", cxx_record_decl->getName().str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Enum:
|
||||
{
|
||||
clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
|
||||
if (enum_decl)
|
||||
{
|
||||
printf("enum %s", enum_decl->getName().str().c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case clang::Type::ObjCObject:
|
||||
case clang::Type::ObjCInterface:
|
||||
{
|
||||
const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
|
||||
if (objc_class_type)
|
||||
{
|
||||
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
// We currently can't complete objective C types through the newly added ASTContext
|
||||
// because it only supports TagDecl objects right now...
|
||||
if (class_interface_decl)
|
||||
printf("@class %s", class_interface_decl->getName().str().c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case clang::Type::Typedef:
|
||||
printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getName().str().c_str());
|
||||
break;
|
||||
|
||||
case clang::Type::Elaborated:
|
||||
printf("elaborated ");
|
||||
return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
|
||||
|
||||
case clang::Type::Paren:
|
||||
printf("paren ");
|
||||
return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
|
||||
|
||||
default:
|
||||
printf("ClangASTContext::DumpTypeName() type_class = %u", type_class);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
clang::ClassTemplateDecl *
|
||||
ClangASTContext::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
|
||||
lldb::AccessType access_type,
|
||||
|
|
|
@ -67,6 +67,31 @@ ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
|
|||
return CopyType (dst_ast, src_ast, QualType::getFromOpaquePtr(type)).getAsOpaquePtr();
|
||||
}
|
||||
|
||||
CompilerType
|
||||
ClangASTImporter::CopyType (ClangASTContext &dst_ast,
|
||||
const CompilerType &src_type)
|
||||
{
|
||||
clang::ASTContext *dst_clang_ast = dst_ast.getASTContext();
|
||||
if (dst_clang_ast)
|
||||
{
|
||||
ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
|
||||
if (src_ast)
|
||||
{
|
||||
clang::ASTContext *src_clang_ast = src_ast->getASTContext();
|
||||
if (src_clang_ast)
|
||||
{
|
||||
lldb::opaque_compiler_type_t dst_clang_type = CopyType(dst_clang_ast,
|
||||
src_clang_ast,
|
||||
src_type.GetOpaqueQualType());
|
||||
|
||||
if (dst_clang_type)
|
||||
return CompilerType(&dst_ast, dst_clang_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return CompilerType();
|
||||
}
|
||||
|
||||
clang::Decl *
|
||||
ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
|
||||
clang::ASTContext *src_ast,
|
||||
|
@ -428,6 +453,68 @@ ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ClangASTImporter::CompleteAndFetchChildren (clang::QualType type)
|
||||
{
|
||||
if (!RequireCompleteType(type))
|
||||
return false;
|
||||
|
||||
if (const TagType *tag_type = type->getAs<TagType>())
|
||||
{
|
||||
TagDecl *tag_decl = tag_type->getDecl();
|
||||
|
||||
DeclOrigin decl_origin = GetDeclOrigin(tag_decl);
|
||||
|
||||
if (!decl_origin.Valid())
|
||||
return false;
|
||||
|
||||
MinionSP minion_sp (GetMinion(&tag_decl->getASTContext(), decl_origin.ctx));
|
||||
|
||||
TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
|
||||
|
||||
for (Decl *origin_child_decl : origin_tag_decl->decls())
|
||||
{
|
||||
minion_sp->Import(origin_child_decl);
|
||||
}
|
||||
|
||||
if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
|
||||
{
|
||||
record_decl->setHasLoadedFieldsFromExternalStorage(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>())
|
||||
{
|
||||
if (ObjCInterfaceDecl *objc_interface_decl = objc_object_type->getInterface())
|
||||
{
|
||||
DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl);
|
||||
|
||||
if (!decl_origin.Valid())
|
||||
return false;
|
||||
|
||||
MinionSP minion_sp (GetMinion(&objc_interface_decl->getASTContext(), decl_origin.ctx));
|
||||
|
||||
ObjCInterfaceDecl *origin_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl);
|
||||
|
||||
for (Decl *origin_child_decl : origin_interface_decl->decls())
|
||||
{
|
||||
minion_sp->Import(origin_child_decl);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ClangASTImporter::RequireCompleteType (clang::QualType type)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#endif
|
||||
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace lldb_private;
|
||||
|
@ -160,3 +161,16 @@ ClangExternalASTSourceCallbacks::layoutRecordType(
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ClangExternalASTSourceCallbacks::FindExternalLexicalDecls (const clang::DeclContext *decl_ctx,
|
||||
llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
|
||||
llvm::SmallVectorImpl<clang::Decl *> &decls)
|
||||
{
|
||||
if (m_callback_tag_decl && decl_ctx)
|
||||
{
|
||||
clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(const_cast<clang::DeclContext *>(decl_ctx));
|
||||
if (tag_decl)
|
||||
CompleteType(tag_decl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,3 +142,11 @@ SymbolFile::FindTypes (const SymbolContext& sc, const ConstString &name, const C
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
SymbolFile::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types)
|
||||
{
|
||||
if (!append)
|
||||
types.Clear();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -360,6 +360,21 @@ SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types)
|
||||
{
|
||||
ModuleSP module_sp(GetModule());
|
||||
if (module_sp)
|
||||
{
|
||||
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
|
||||
if (m_sym_file_ap.get())
|
||||
return m_sym_file_ap->FindTypes(context, append, types);
|
||||
}
|
||||
if (!append)
|
||||
types.Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
SymbolVendor::GetTypes (SymbolContextScope *sc_scope,
|
||||
uint32_t type_mask,
|
||||
|
|
|
@ -7,8 +7,12 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Other libraries and framework includes
|
||||
// C Includes
|
||||
#include <stdio.h>
|
||||
|
||||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
|
@ -36,6 +40,27 @@
|
|||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
void
|
||||
CompilerContext::Dump() const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CompilerContextKind::Invalid: printf("Invalid"); break;
|
||||
case CompilerContextKind::TranslationUnit: printf("TranslationUnit"); break;
|
||||
case CompilerContextKind::Module: printf("Module"); break;
|
||||
case CompilerContextKind::Namespace: printf("Namespace"); break;
|
||||
case CompilerContextKind::Class: printf("Class"); break;
|
||||
case CompilerContextKind::Structure: printf("Structure"); break;
|
||||
case CompilerContextKind::Union: printf("Union"); break;
|
||||
case CompilerContextKind::Function: printf("Function"); break;
|
||||
case CompilerContextKind::Variable: printf("Variable"); break;
|
||||
case CompilerContextKind::Enumeration: printf("Enumeration"); break;
|
||||
case CompilerContextKind::Typedef: printf("Typedef"); break;
|
||||
default: printf("???(%u)", type);
|
||||
}
|
||||
printf("(\"%s\")\n", name.GetCString());
|
||||
}
|
||||
|
||||
class TypeAppendVisitor
|
||||
{
|
||||
public:
|
||||
|
@ -62,6 +87,13 @@ TypeListImpl::Append (const lldb_private::TypeList &type_list)
|
|||
type_list.ForEach(cb);
|
||||
}
|
||||
|
||||
SymbolFileType::SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp) :
|
||||
UserID (type_sp ? type_sp->GetID() : LLDB_INVALID_UID),
|
||||
m_symbol_file (symbol_file),
|
||||
m_type_sp (type_sp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Type *
|
||||
SymbolFileType::GetType ()
|
||||
|
|
Loading…
Reference in New Issue