forked from OSchip/llvm-project
Trying to submit 254476 one more time. This implement -gmodule debugging support.
It was previously reverted due to issues that showed up only on linux. I was able to reproduce these issues and fix the underlying cause. So this is the same patch as 254476 with the following two fixes: - Fix not trying to complete classes that don't have external sources - Fix ClangASTSource::CompleteType() to check the decl context of types that it finds by basename to ensure we don't complete a type "S" with a type like "std::S". Before this fix ClangASTSource::CompleteType() would accept _any_ type that had a matching basename and copy it into the other type. <rdar://problem/22992457> llvm-svn: 254980
This commit is contained in:
parent
de02939823
commit
e6b36cdd4d
|
@ -151,7 +151,16 @@ public:
|
||||||
{
|
{
|
||||||
return ClangASTContext::GetCompleteDecl(getASTContext(), decl);
|
return ClangASTContext::GetCompleteDecl(getASTContext(), decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DumpDeclHiearchy (clang::Decl *decl);
|
||||||
|
|
||||||
|
static void
|
||||||
|
DumpDeclContextHiearchy (clang::DeclContext *decl_ctx);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
DeclsAreEquivalent (clang::Decl *lhs_decl, clang::Decl *rhs_decl);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
GetCompleteDecl (clang::ASTContext *ast,
|
GetCompleteDecl (clang::ASTContext *ast,
|
||||||
clang::Decl *decl);
|
clang::Decl *decl);
|
||||||
|
@ -1006,10 +1015,18 @@ public:
|
||||||
lldb::AccessType access,
|
lldb::AccessType access,
|
||||||
bool is_artificial);
|
bool is_artificial);
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern);
|
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
|
// Tag Declarations
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -1092,13 +1109,19 @@ public:
|
||||||
|
|
||||||
void
|
void
|
||||||
DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) override;
|
DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) override;
|
||||||
|
|
||||||
|
static void
|
||||||
|
DumpTypeName (const CompilerType &type);
|
||||||
|
|
||||||
static clang::EnumDecl *
|
static clang::EnumDecl *
|
||||||
GetAsEnumDecl (const CompilerType& type);
|
GetAsEnumDecl (const CompilerType& type);
|
||||||
|
|
||||||
static clang::RecordDecl *
|
static clang::RecordDecl *
|
||||||
GetAsRecordDecl (const CompilerType& type);
|
GetAsRecordDecl (const CompilerType& type);
|
||||||
|
|
||||||
|
static clang::TagDecl *
|
||||||
|
GetAsTagDecl (const CompilerType& type);
|
||||||
|
|
||||||
clang::CXXRecordDecl *
|
clang::CXXRecordDecl *
|
||||||
GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type);
|
GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type);
|
||||||
|
|
||||||
|
@ -1109,9 +1132,12 @@ public:
|
||||||
GetQualType (const CompilerType& type)
|
GetQualType (const CompilerType& type)
|
||||||
{
|
{
|
||||||
// Make sure we have a clang type before making a clang::QualType
|
// Make sure we have a clang type before making a clang::QualType
|
||||||
ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
|
if (type.GetOpaqueQualType())
|
||||||
if (ast)
|
{
|
||||||
return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType());
|
ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
|
||||||
|
if (ast)
|
||||||
|
return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType());
|
||||||
|
}
|
||||||
return clang::QualType();
|
return clang::QualType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,11 @@ public:
|
||||||
CopyType (clang::ASTContext *dst_ctx,
|
CopyType (clang::ASTContext *dst_ctx,
|
||||||
clang::ASTContext *src_ctx,
|
clang::ASTContext *src_ctx,
|
||||||
lldb::opaque_compiler_type_t type);
|
lldb::opaque_compiler_type_t type);
|
||||||
|
|
||||||
|
CompilerType
|
||||||
|
CopyType (ClangASTContext &dst,
|
||||||
|
const CompilerType &src_type);
|
||||||
|
|
||||||
clang::Decl *
|
clang::Decl *
|
||||||
CopyDecl (clang::ASTContext *dst_ctx,
|
CopyDecl (clang::ASTContext *dst_ctx,
|
||||||
clang::ASTContext *src_ctx,
|
clang::ASTContext *src_ctx,
|
||||||
|
@ -134,7 +138,10 @@ public:
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
|
CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
|
||||||
|
|
||||||
|
bool
|
||||||
|
CompleteAndFetchChildren (clang::QualType type);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RequireCompleteType (clang::QualType type);
|
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;
|
bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName decl_name) override;
|
||||||
|
|
||||||
void CompleteType(clang::TagDecl *tag_decl) override;
|
void CompleteType(clang::TagDecl *tag_decl) override;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "lldb/Symbol/CompilerType.h"
|
#include "lldb/Symbol/CompilerType.h"
|
||||||
#include "lldb/Symbol/CompilerDecl.h"
|
#include "lldb/Symbol/CompilerDecl.h"
|
||||||
#include "lldb/Symbol/CompilerDeclContext.h"
|
#include "lldb/Symbol/CompilerDeclContext.h"
|
||||||
|
|
||||||
#include "lldb/Symbol/Type.h"
|
#include "lldb/Symbol/Type.h"
|
||||||
|
|
||||||
namespace lldb_private {
|
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 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 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 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 uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0;
|
||||||
virtual TypeList * GetTypeList ();
|
virtual TypeList * GetTypeList ();
|
||||||
virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
|
virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
|
||||||
|
|
|
@ -128,6 +128,9 @@ public:
|
||||||
size_t max_matches,
|
size_t max_matches,
|
||||||
TypeMap& types);
|
TypeMap& types);
|
||||||
|
|
||||||
|
virtual size_t
|
||||||
|
FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
|
||||||
|
|
||||||
virtual CompilerDeclContext
|
virtual CompilerDeclContext
|
||||||
FindNamespace (const SymbolContext& sc,
|
FindNamespace (const SymbolContext& sc,
|
||||||
const ConstString &name,
|
const ConstString &name,
|
||||||
|
|
|
@ -24,6 +24,31 @@
|
||||||
|
|
||||||
namespace lldb_private {
|
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 :
|
class SymbolFileType :
|
||||||
public std::enable_shared_from_this<SymbolFileType>,
|
public std::enable_shared_from_this<SymbolFileType>,
|
||||||
public UserID
|
public UserID
|
||||||
|
@ -35,6 +60,9 @@ class SymbolFileType :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp);
|
||||||
|
|
||||||
|
|
||||||
~SymbolFileType ()
|
~SymbolFileType ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ class CommandObject;
|
||||||
class CommandReturnObject;
|
class CommandReturnObject;
|
||||||
class Communication;
|
class Communication;
|
||||||
class CompactUnwindInfo;
|
class CompactUnwindInfo;
|
||||||
|
struct CompilerContext;
|
||||||
class CompilerDecl;
|
class CompilerDecl;
|
||||||
class CompilerDeclContext;
|
class CompilerDeclContext;
|
||||||
class CompilerType;
|
class CompilerType;
|
||||||
|
|
|
@ -241,6 +241,25 @@ enum class TypeValidatorResult : bool {
|
||||||
Success = true,
|
Success = true,
|
||||||
Failure = false
|
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
|
} // namespace lldb_private
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,11 @@ class TestCppIncompleteTypes(TestBase):
|
||||||
|
|
||||||
value_f = frame.EvaluateExpression("f")
|
value_f = frame.EvaluateExpression("f")
|
||||||
self.assertTrue(value_f.IsValid(), "'expr f' results in a valid SBValue object")
|
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")
|
value_a = frame.EvaluateExpression("a")
|
||||||
self.assertTrue(value_a.IsValid(), "'expr a' results in a valid SBValue object")
|
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
|
@skipIfGcc
|
||||||
@skipIfWindows # Clang on Windows asserts in external record layout in this case.
|
@skipIfWindows # Clang on Windows asserts in external record layout in this case.
|
||||||
|
|
|
@ -322,6 +322,11 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
|
||||||
|
|
||||||
TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
|
TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
|
||||||
|
|
||||||
|
// We have found a type by basename and we need to make sure the decl contexts
|
||||||
|
// are the same before we can try to complete this type with another
|
||||||
|
if (!ClangASTContext::DeclsAreEquivalent (tag_decl, candidate_tag_decl))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
|
if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,18 @@ public:
|
||||||
ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
|
ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
|
||||||
const DWARFDIE &die) = 0;
|
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
|
virtual bool
|
||||||
CompleteTypeFromDWARF (const DWARFDIE &die,
|
CompleteTypeFromDWARF (const DWARFDIE &die,
|
||||||
lldb_private::Type *type,
|
lldb_private::Type *type,
|
||||||
|
|
|
@ -24,11 +24,14 @@
|
||||||
#include "lldb/Core/StreamString.h"
|
#include "lldb/Core/StreamString.h"
|
||||||
#include "lldb/Core/Value.h"
|
#include "lldb/Core/Value.h"
|
||||||
#include "lldb/Host/Host.h"
|
#include "lldb/Host/Host.h"
|
||||||
|
#include "lldb/Symbol/ClangASTImporter.h"
|
||||||
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
|
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
|
||||||
#include "lldb/Symbol/CompileUnit.h"
|
#include "lldb/Symbol/CompileUnit.h"
|
||||||
#include "lldb/Symbol/Function.h"
|
#include "lldb/Symbol/Function.h"
|
||||||
#include "lldb/Symbol/ObjectFile.h"
|
#include "lldb/Symbol/ObjectFile.h"
|
||||||
|
#include "lldb/Symbol/SymbolVendor.h"
|
||||||
#include "lldb/Symbol/TypeList.h"
|
#include "lldb/Symbol/TypeList.h"
|
||||||
|
#include "lldb/Symbol/TypeMap.h"
|
||||||
#include "lldb/Target/Language.h"
|
#include "lldb/Target/Language.h"
|
||||||
#include "Plugins/Language/ObjC/ObjCLanguage.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
|
TypeSP
|
||||||
DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
|
DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
|
||||||
const DWARFDIE &die,
|
const DWARFDIE &die,
|
||||||
|
@ -487,15 +562,15 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
|
||||||
if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
|
if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
|
||||||
byte_size_valid ? byte_size : -1,
|
byte_size_valid ? byte_size : -1,
|
||||||
*unique_ast_entry_ap))
|
*unique_ast_entry_ap))
|
||||||
{
|
|
||||||
type_sp = unique_ast_entry_ap->m_type_sp;
|
|
||||||
if (type_sp)
|
|
||||||
{
|
{
|
||||||
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
|
type_sp = unique_ast_entry_ap->m_type_sp;
|
||||||
return 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);
|
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);
|
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;
|
DWARFDeclContext die_decl_ctx;
|
||||||
die.GetDWARFDeclContext(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_type: encoding_form = form_value; break;
|
||||||
case DW_AT_byte_size: byte_size = form_value.Unsigned(); 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_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_allocated:
|
||||||
case DW_AT_associated:
|
case DW_AT_associated:
|
||||||
case DW_AT_bit_stride:
|
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);
|
DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
|
||||||
|
|
||||||
CompilerType enumerator_clang_type;
|
CompilerType enumerator_clang_type;
|
||||||
|
@ -1130,7 +1258,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
|
||||||
if (class_type)
|
if (class_type)
|
||||||
{
|
{
|
||||||
bool alternate_defn = false;
|
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;
|
alternate_defn = true;
|
||||||
|
|
||||||
|
@ -1797,6 +1925,33 @@ DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die,
|
||||||
return template_param_infos.args.size() == template_param_infos.names.size();
|
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
|
bool
|
||||||
DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
|
DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
|
||||||
lldb_private::Type *type,
|
lldb_private::Type *type,
|
||||||
|
@ -1868,25 +2023,17 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
|
||||||
DWARFDIECollection member_function_dies;
|
DWARFDIECollection member_function_dies;
|
||||||
|
|
||||||
DelayedPropertyList delayed_properties;
|
DelayedPropertyList delayed_properties;
|
||||||
if (!ParseChildMembers (sc,
|
ParseChildMembers (sc,
|
||||||
die,
|
die,
|
||||||
clang_type,
|
clang_type,
|
||||||
class_language,
|
class_language,
|
||||||
base_classes,
|
base_classes,
|
||||||
member_accessibilities,
|
member_accessibilities,
|
||||||
member_function_dies,
|
member_function_dies,
|
||||||
delayed_properties,
|
delayed_properties,
|
||||||
default_accessibility,
|
default_accessibility,
|
||||||
is_a_class,
|
is_a_class,
|
||||||
layout_info))
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now parse any methods if there were any...
|
// Now parse any methods if there were any...
|
||||||
size_t num_functions = member_function_dies.Size();
|
size_t num_functions = member_function_dies.Size();
|
||||||
|
@ -1977,7 +2124,14 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
|
||||||
if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
|
if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
|
||||||
module->ReportError (":: Try compiling the source file with -fno-limit-debug-info.");
|
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)
|
if (!parent_die)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t incomplete_member_info_count = 0;
|
|
||||||
uint32_t member_idx = 0;
|
uint32_t member_idx = 0;
|
||||||
BitfieldInfo last_field_info;
|
BitfieldInfo last_field_info;
|
||||||
|
|
||||||
|
@ -2754,8 +2907,8 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
|
||||||
}
|
}
|
||||||
|
|
||||||
CompilerType member_clang_type = member_type->GetLayoutCompilerType ();
|
CompilerType member_clang_type = member_type->GetLayoutCompilerType ();
|
||||||
if (!member_clang_type.IsCompleteType() && !member_clang_type.GetCompleteType())
|
if (!member_clang_type.IsCompleteType())
|
||||||
incomplete_member_info_count += 1;
|
member_clang_type.GetCompleteType();
|
||||||
|
|
||||||
{
|
{
|
||||||
// Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>).
|
// 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,
|
field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type,
|
||||||
name,
|
name,
|
||||||
member_clang_type,
|
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,
|
ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
|
||||||
const DWARFDIE &die) override;
|
const DWARFDIE &die) override;
|
||||||
|
|
||||||
|
bool
|
||||||
|
CanCompleteType (const lldb_private::CompilerType &compiler_type) override;
|
||||||
|
|
||||||
|
bool
|
||||||
|
CompleteType (const lldb_private::CompilerType &compiler_type) override;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CompleteTypeFromDWARF (const DWARFDIE &die,
|
CompleteTypeFromDWARF (const DWARFDIE &die,
|
||||||
lldb_private::Type *type,
|
lldb_private::Type *type,
|
||||||
|
@ -175,6 +181,19 @@ protected:
|
||||||
void
|
void
|
||||||
LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die);
|
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::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
|
||||||
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
|
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
|
||||||
//typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
|
//typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
|
||||||
|
@ -188,6 +207,7 @@ protected:
|
||||||
DIEToDeclContextMap m_die_to_decl_ctx;
|
DIEToDeclContextMap m_die_to_decl_ctx;
|
||||||
DeclContextToDIEMap m_decl_ctx_to_die;
|
DeclContextToDIEMap m_decl_ctx_to_die;
|
||||||
RecordDeclToLayoutMap m_record_decl_to_layout_map;
|
RecordDeclToLayoutMap m_record_decl_to_layout_map;
|
||||||
|
std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SymbolFileDWARF_DWARFASTParserClang_h_
|
#endif // SymbolFileDWARF_DWARFASTParserClang_h_
|
||||||
|
|
|
@ -22,8 +22,11 @@
|
||||||
|
|
||||||
#include "lldb/Core/Module.h"
|
#include "lldb/Core/Module.h"
|
||||||
#include "lldb/Symbol/ObjectFile.h"
|
#include "lldb/Symbol/ObjectFile.h"
|
||||||
|
#include "lldb/Symbol/Type.h"
|
||||||
#include "lldb/Symbol/TypeSystem.h"
|
#include "lldb/Symbol/TypeSystem.h"
|
||||||
|
|
||||||
|
using namespace lldb_private;
|
||||||
|
|
||||||
DIERef
|
DIERef
|
||||||
DWARFDIE::GetDIERef() const
|
DWARFDIE::GetDIERef() const
|
||||||
{
|
{
|
||||||
|
@ -307,6 +310,50 @@ 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:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DWARFDIE
|
DWARFDIE
|
||||||
DWARFDIE::GetParentDeclContextDIE () const
|
DWARFDIE::GetParentDeclContextDIE () const
|
||||||
|
@ -371,6 +418,45 @@ DWARFDIE::IsStructOrClass () const
|
||||||
return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
|
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
|
bool
|
||||||
DWARFDIE::HasChildren () const
|
DWARFDIE::HasChildren () const
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,6 +126,12 @@ public:
|
||||||
m_die = nullptr;
|
m_die = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lldb::ModuleSP
|
||||||
|
GetContainingDWOModule () const;
|
||||||
|
|
||||||
|
DWARFDIE
|
||||||
|
GetContainingDWOModuleDIE () const;
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Accessing information about a DIE
|
// Accessing information about a DIE
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
@ -217,6 +223,9 @@ public:
|
||||||
void
|
void
|
||||||
GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const;
|
GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const;
|
||||||
|
|
||||||
|
void
|
||||||
|
GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const;
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Getting attribute values from the DIE.
|
// 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()))
|
if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage()))
|
||||||
{
|
{
|
||||||
UpdateExternalModuleListIfNeeded();
|
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)
|
SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type)
|
||||||
{
|
{
|
||||||
CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(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
|
bool
|
||||||
SymbolFileDWARF::CompleteType (CompilerType &compiler_type)
|
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.
|
// We have a struct/union/class/enum that needs to be fully resolved.
|
||||||
CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
|
CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
|
||||||
auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType());
|
auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType());
|
||||||
|
@ -1641,6 +1660,17 @@ SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc)
|
||||||
return false;
|
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
|
void
|
||||||
SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
|
SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
|
||||||
{
|
{
|
||||||
|
@ -1658,37 +1688,24 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
|
||||||
const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
|
const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
|
||||||
if (die && die.HasChildren() == false)
|
if (die && die.HasChildren() == false)
|
||||||
{
|
{
|
||||||
const uint64_t name_strp = die.GetAttributeValueAsUnsigned (DW_AT_name, UINT64_MAX);
|
const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
|
||||||
const uint64_t dwo_path_strp = die.GetAttributeValueAsUnsigned (DW_AT_GNU_dwo_name, UINT64_MAX);
|
|
||||||
|
if (name)
|
||||||
if (name_strp != UINT64_MAX)
|
|
||||||
{
|
{
|
||||||
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);
|
ModuleSP module_sp;
|
||||||
const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp);
|
const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
|
||||||
if (name || dwo_path)
|
if (dwo_path)
|
||||||
{
|
{
|
||||||
ModuleSP module_sp;
|
ModuleSpec dwo_module_spec;
|
||||||
if (dwo_path)
|
dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
|
||||||
{
|
dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
|
||||||
ModuleSpec dwo_module_spec;
|
//printf ("Loading dwo = '%s'\n", dwo_path);
|
||||||
dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
|
Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
|
||||||
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 };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
m_external_type_modules[const_name] = module_sp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2970,6 +2987,104 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
|
||||||
}
|
}
|
||||||
return num_matches;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,6 +211,11 @@ public:
|
||||||
uint32_t max_matches,
|
uint32_t max_matches,
|
||||||
lldb_private::TypeMap& types) override;
|
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 *
|
lldb_private::TypeList *
|
||||||
GetTypeList () override;
|
GetTypeList () override;
|
||||||
|
|
||||||
|
@ -306,6 +311,9 @@ public:
|
||||||
virtual lldb_private::DWARFExpression::LocationListFormat
|
virtual lldb_private::DWARFExpression::LocationListFormat
|
||||||
GetLocationListFormat() const;
|
GetLocationListFormat() const;
|
||||||
|
|
||||||
|
lldb::ModuleSP
|
||||||
|
GetDWOModule (lldb_private::ConstString name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
|
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
|
||||||
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
|
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
|
||||||
|
@ -483,12 +491,7 @@ protected:
|
||||||
|
|
||||||
typedef std::set<lldb_private::Type *> TypeSet;
|
typedef std::set<lldb_private::Type *> TypeSet;
|
||||||
|
|
||||||
typedef struct {
|
typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap;
|
||||||
lldb_private::ConstString m_name;
|
|
||||||
lldb::ModuleSP m_module_sp;
|
|
||||||
} ClangModuleInfo;
|
|
||||||
|
|
||||||
typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GetTypes (const DWARFDIE &die,
|
GetTypes (const DWARFDIE &die,
|
||||||
|
|
|
@ -2280,6 +2280,157 @@ ClangASTContext::GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed)
|
||||||
return CompilerType();
|
return CompilerType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClangASTContext::DumpDeclContextHiearchy (clang::DeclContext *decl_ctx)
|
||||||
|
{
|
||||||
|
if (decl_ctx)
|
||||||
|
{
|
||||||
|
DumpDeclContextHiearchy (decl_ctx->getParent());
|
||||||
|
|
||||||
|
clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx);
|
||||||
|
if (named_decl)
|
||||||
|
{
|
||||||
|
printf ("%20s: %s\n", decl_ctx->getDeclKindName(), named_decl->getDeclName().getAsString().c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("%20s\n", decl_ctx->getDeclKindName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClangASTContext::DumpDeclHiearchy (clang::Decl *decl)
|
||||||
|
{
|
||||||
|
if (decl == nullptr)
|
||||||
|
return;
|
||||||
|
DumpDeclContextHiearchy(decl->getDeclContext());
|
||||||
|
|
||||||
|
clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl);
|
||||||
|
if (record_decl)
|
||||||
|
{
|
||||||
|
printf ("%20s: %s%s\n", decl->getDeclKindName(), record_decl->getDeclName().getAsString().c_str(), record_decl->isInjectedClassName() ? " (injected class name)" : "");
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl);
|
||||||
|
if (named_decl)
|
||||||
|
{
|
||||||
|
printf ("%20s: %s\n", decl->getDeclKindName(), named_decl->getDeclName().getAsString().c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("%20s\n", decl->getDeclKindName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ClangASTContext::DeclsAreEquivalent (clang::Decl *lhs_decl, clang::Decl *rhs_decl)
|
||||||
|
{
|
||||||
|
if (lhs_decl && rhs_decl)
|
||||||
|
{
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Make sure the decl kinds match first
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind();
|
||||||
|
const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind();
|
||||||
|
|
||||||
|
if (lhs_decl_kind == rhs_decl_kind)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
// Now check that the decl contexts kinds are all equivalent
|
||||||
|
// before we have to check any names of the decl contexts...
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext();
|
||||||
|
clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext();
|
||||||
|
if (lhs_decl_ctx && rhs_decl_ctx)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (lhs_decl_ctx && rhs_decl_ctx)
|
||||||
|
{
|
||||||
|
const clang::Decl::Kind lhs_decl_ctx_kind = lhs_decl_ctx->getDeclKind();
|
||||||
|
const clang::Decl::Kind rhs_decl_ctx_kind = rhs_decl_ctx->getDeclKind();
|
||||||
|
if (lhs_decl_ctx_kind == rhs_decl_ctx_kind)
|
||||||
|
{
|
||||||
|
lhs_decl_ctx = lhs_decl_ctx->getParent();
|
||||||
|
rhs_decl_ctx = rhs_decl_ctx->getParent();
|
||||||
|
|
||||||
|
if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
// Now make sure the name of the decls match
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl);
|
||||||
|
clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl);
|
||||||
|
if (lhs_named_decl && rhs_named_decl)
|
||||||
|
{
|
||||||
|
clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
|
||||||
|
clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
|
||||||
|
if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind())
|
||||||
|
{
|
||||||
|
if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
// We know that the decl context kinds all match, so now we need
|
||||||
|
// to make sure the names match as well
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
lhs_decl_ctx = lhs_decl->getDeclContext();
|
||||||
|
rhs_decl_ctx = rhs_decl->getDeclContext();
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
switch (lhs_decl_ctx->getDeclKind())
|
||||||
|
{
|
||||||
|
case clang::Decl::TranslationUnit:
|
||||||
|
// We don't care about the translation unit names
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx);
|
||||||
|
clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx);
|
||||||
|
if (lhs_named_decl && rhs_named_decl)
|
||||||
|
{
|
||||||
|
clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
|
||||||
|
clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
|
||||||
|
if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind())
|
||||||
|
{
|
||||||
|
if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
lhs_decl_ctx = lhs_decl_ctx->getParent();
|
||||||
|
rhs_decl_ctx = rhs_decl_ctx->getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool
|
bool
|
||||||
ClangASTContext::GetCompleteDecl (clang::ASTContext *ast,
|
ClangASTContext::GetCompleteDecl (clang::ASTContext *ast,
|
||||||
clang::Decl *decl)
|
clang::Decl *decl)
|
||||||
|
@ -2451,81 +2602,112 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool all
|
||||||
case clang::Type::ConstantArray:
|
case clang::Type::ConstantArray:
|
||||||
case clang::Type::IncompleteArray:
|
case clang::Type::IncompleteArray:
|
||||||
case clang::Type::VariableArray:
|
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);
|
|
||||||
}
|
|
||||||
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();
|
const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
|
||||||
if (tag_decl)
|
|
||||||
|
if (array_type)
|
||||||
|
return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case clang::Type::Record:
|
||||||
|
{
|
||||||
|
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||||
|
if (cxx_record_decl)
|
||||||
{
|
{
|
||||||
if (tag_decl->isCompleteDefinition())
|
if (cxx_record_decl->hasExternalLexicalStorage())
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!allow_completion)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (tag_decl->hasExternalLexicalStorage())
|
|
||||||
{
|
{
|
||||||
if (ast)
|
const bool is_complete = cxx_record_decl->isCompleteDefinition();
|
||||||
|
const bool fields_loaded = cxx_record_decl->hasLoadedFieldsFromExternalStorage();
|
||||||
|
if (is_complete && fields_loaded)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!allow_completion)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
|
external_ast_source->CompleteType(cxx_record_decl);
|
||||||
if (external_ast_source)
|
if (cxx_record_decl->isCompleteDefinition())
|
||||||
{
|
{
|
||||||
external_ast_source->CompleteType(tag_decl);
|
cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true);
|
||||||
return !tag_type->isIncompleteType();
|
cxx_record_decl->field_begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
const clang::TagType *tag_type = llvm::cast<clang::TagType>(qual_type.getTypePtr());
|
||||||
|
return !tag_type->isIncompleteType();
|
||||||
|
}
|
||||||
|
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;
|
break;
|
||||||
|
|
||||||
case clang::Type::ObjCObject:
|
case clang::Type::ObjCObject:
|
||||||
case clang::Type::ObjCInterface:
|
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();
|
const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
|
||||||
// We currently can't complete objective C types through the newly added ASTContext
|
if (objc_class_type)
|
||||||
// because it only supports TagDecl objects right now...
|
|
||||||
if (class_interface_decl)
|
|
||||||
{
|
{
|
||||||
if (class_interface_decl->getDefinition())
|
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||||
return true;
|
// We currently can't complete objective C types through the newly added ASTContext
|
||||||
|
// because it only supports TagDecl objects right now...
|
||||||
if (!allow_completion)
|
if (class_interface_decl)
|
||||||
return false;
|
|
||||||
|
|
||||||
if (class_interface_decl->hasExternalLexicalStorage())
|
|
||||||
{
|
{
|
||||||
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 (ast)
|
||||||
if (external_ast_source)
|
|
||||||
{
|
{
|
||||||
external_ast_source->CompleteType (class_interface_decl);
|
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
|
||||||
return !objc_class_type->isIncompleteType();
|
if (external_ast_source)
|
||||||
|
{
|
||||||
|
external_ast_source->CompleteType (class_interface_decl);
|
||||||
|
return !objc_class_type->isIncompleteType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case clang::Type::Typedef:
|
case clang::Type::Typedef:
|
||||||
|
@ -2536,7 +2718,10 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool all
|
||||||
|
|
||||||
case clang::Type::Paren:
|
case clang::Type::Paren:
|
||||||
return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion);
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -7160,6 +7345,16 @@ ClangASTContext::GetAsRecordDecl (const CompilerType& type)
|
||||||
return nullptr;
|
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 *
|
clang::CXXRecordDecl *
|
||||||
ClangASTContext::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type)
|
ClangASTContext::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type)
|
||||||
{
|
{
|
||||||
|
@ -8036,6 +8231,64 @@ ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type,
|
||||||
return objc_method_decl;
|
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
|
bool
|
||||||
ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern)
|
ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern)
|
||||||
{
|
{
|
||||||
|
@ -8106,38 +8359,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
|
#pragma mark TagDecl
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
|
ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
|
||||||
{
|
{
|
||||||
if (type)
|
clang::QualType qual_type (ClangASTContext::GetQualType(type));
|
||||||
|
if (!qual_type.isNull())
|
||||||
{
|
{
|
||||||
|
const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
|
||||||
clang::QualType qual_type (GetQualType(type));
|
if (tag_type)
|
||||||
const clang::Type *t = qual_type.getTypePtr();
|
|
||||||
if (t)
|
|
||||||
{
|
{
|
||||||
const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(t);
|
clang::TagDecl *tag_decl = tag_type->getDecl();
|
||||||
if (tag_type)
|
if (tag_decl)
|
||||||
{
|
{
|
||||||
clang::TagDecl *tag_decl = tag_type->getDecl();
|
tag_decl->startDefinition();
|
||||||
if (tag_decl)
|
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();
|
interface_decl->startDefinition();
|
||||||
if (interface_decl)
|
return true;
|
||||||
{
|
|
||||||
interface_decl->startDefinition();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8147,26 +8535,22 @@ ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
|
||||||
bool
|
bool
|
||||||
ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type)
|
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();
|
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||||
|
|
||||||
if (cxx_record_decl)
|
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;
|
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)
|
if (enutype)
|
||||||
{
|
{
|
||||||
|
@ -8174,25 +8558,33 @@ ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type)
|
||||||
|
|
||||||
if (enum_decl)
|
if (enum_decl)
|
||||||
{
|
{
|
||||||
/// TODO This really needs to be fixed.
|
if (!enum_decl->isCompleteDefinition())
|
||||||
|
|
||||||
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())
|
ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
|
||||||
promotion_qual_type = ast->IntTy;
|
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
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8976,6 +9368,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 *
|
clang::ClassTemplateDecl *
|
||||||
ClangASTContext::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
|
ClangASTContext::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
|
||||||
lldb::AccessType access_type,
|
lldb::AccessType access_type,
|
||||||
|
|
|
@ -67,6 +67,31 @@ ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
|
||||||
return CopyType (dst_ast, src_ast, QualType::getFromOpaquePtr(type)).getAsOpaquePtr();
|
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 *
|
clang::Decl *
|
||||||
ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
|
ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
|
||||||
clang::ASTContext *src_ast,
|
clang::ASTContext *src_ast,
|
||||||
|
@ -428,6 +453,68 @@ ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface
|
||||||
return true;
|
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
|
bool
|
||||||
ClangASTImporter::RequireCompleteType (clang::QualType type)
|
ClangASTImporter::RequireCompleteType (clang::QualType type)
|
||||||
{
|
{
|
||||||
|
@ -793,10 +880,14 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
|
||||||
{
|
{
|
||||||
if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
|
if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
|
||||||
{
|
{
|
||||||
NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
|
RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from);
|
||||||
|
if (from_record_decl == nullptr || from_record_decl->isInjectedClassName() == false)
|
||||||
|
{
|
||||||
|
NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
|
||||||
|
|
||||||
if (!m_decls_already_deported->count(to_named_decl))
|
if (!m_decls_already_deported->count(to_named_decl))
|
||||||
m_decls_to_deport->insert(to_named_decl);
|
m_decls_to_deport->insert(to_named_decl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "lldb/Core/Log.h"
|
#include "lldb/Core/Log.h"
|
||||||
|
#include "clang/AST/Decl.h"
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace lldb_private;
|
using namespace lldb_private;
|
||||||
|
@ -160,3 +161,16 @@ ClangExternalASTSourceCallbacks::layoutRecordType(
|
||||||
return false;
|
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;
|
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;
|
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
|
size_t
|
||||||
SymbolVendor::GetTypes (SymbolContextScope *sc_scope,
|
SymbolVendor::GetTypes (SymbolContextScope *sc_scope,
|
||||||
uint32_t type_mask,
|
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/DataExtractor.h"
|
||||||
#include "lldb/Core/DataBufferHeap.h"
|
#include "lldb/Core/DataBufferHeap.h"
|
||||||
#include "lldb/Core/Module.h"
|
#include "lldb/Core/Module.h"
|
||||||
|
@ -36,6 +40,27 @@
|
||||||
using namespace lldb;
|
using namespace lldb;
|
||||||
using namespace lldb_private;
|
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
|
class TypeAppendVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -62,6 +87,13 @@ TypeListImpl::Append (const lldb_private::TypeList &type_list)
|
||||||
type_list.ForEach(cb);
|
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 *
|
Type *
|
||||||
SymbolFileType::GetType ()
|
SymbolFileType::GetType ()
|
||||||
|
|
Loading…
Reference in New Issue