forked from OSchip/llvm-project
Added the ability to create an objective C method for an objective C
interface in ClangASTContext. Also added two bool returning functions that indicated if an opaque clang qual type is a CXX class type, and if it is an ObjC class type. Objective C classes now will get their methods added lazily as they are encountered. The reason for this is currently, unlike C++, the DW_TAG_structure_type and owns the ivars, doesn't not also contain the member functions. This means when we parse the objective C class interface we either need to find all functions whose names start with "+[CLASS_NAME" or "-[CLASS_NAME" and add them all to the class, or when we parse each objective C function, we slowly add it to the class interface definition. Since objective C's class doesn't change internal bits according to whether it has certain types of member functions (like C++ does if it has virtual functions, or if it has user ctors/dtors), I currently chose to lazily populate the class when each functions is parsed. Another issue we run into with ObjC method declarations is the "self" and "_cmd" implicit args are not marked as artificial in the DWARF (DW_AT_artifical), so we currently have to look for the parameters by name if we are trying to omit artificial function args if the language of the compile unit is ObjC or ObjC++. llvm-svn: 114722
This commit is contained in:
parent
45c42ec2f1
commit
0fffff5816
|
@ -174,12 +174,12 @@ public:
|
|||
lldb::AccessType access,
|
||||
uint32_t bitfield_bit_size)
|
||||
{
|
||||
return ClangASTContext::AddFieldToRecordType(getASTContext(),
|
||||
record_qual_type,
|
||||
name,
|
||||
field_type,
|
||||
access,
|
||||
bitfield_bit_size);
|
||||
return ClangASTContext::AddFieldToRecordType (getASTContext(),
|
||||
record_qual_type,
|
||||
name,
|
||||
field_type,
|
||||
access,
|
||||
bitfield_bit_size);
|
||||
}
|
||||
|
||||
static clang::CXXMethodDecl *
|
||||
|
@ -188,22 +188,28 @@ public:
|
|||
const char *name,
|
||||
void *method_type,
|
||||
lldb::AccessType access,
|
||||
bool is_virtual);
|
||||
bool is_virtual,
|
||||
bool is_static,
|
||||
bool is_inline);
|
||||
|
||||
clang::CXXMethodDecl *
|
||||
AddMethodToCXXRecordType (void *record_opaque_type,
|
||||
const char *name,
|
||||
void *method_type,
|
||||
lldb::AccessType access,
|
||||
bool is_virtual)
|
||||
bool is_virtual,
|
||||
bool is_static,
|
||||
bool is_inline)
|
||||
|
||||
{
|
||||
return ClangASTContext::AddMethodToCXXRecordType(getASTContext(),
|
||||
record_opaque_type,
|
||||
name,
|
||||
method_type,
|
||||
access,
|
||||
is_virtual);
|
||||
return ClangASTContext::AddMethodToCXXRecordType (getASTContext(),
|
||||
record_opaque_type,
|
||||
name,
|
||||
method_type,
|
||||
access,
|
||||
is_virtual,
|
||||
is_static,
|
||||
is_inline);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -267,7 +273,28 @@ public:
|
|||
ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl,
|
||||
bool check_superclass);
|
||||
|
||||
|
||||
|
||||
static clang::ObjCMethodDecl *
|
||||
AddMethodToObjCObjectType (clang::ASTContext *ast_context,
|
||||
void *class_opaque_type,
|
||||
const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
|
||||
void *method_opaque_type,
|
||||
lldb::AccessType access);
|
||||
|
||||
clang::ObjCMethodDecl *
|
||||
AddMethodToObjCObjectType (void *class_opaque_type,
|
||||
const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
|
||||
void *method_opaque_type,
|
||||
lldb::AccessType access)
|
||||
{
|
||||
return AddMethodToObjCObjectType (getASTContext(),
|
||||
class_opaque_type,
|
||||
name,
|
||||
method_opaque_type,
|
||||
access);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Aggregate Types
|
||||
//------------------------------------------------------------------
|
||||
|
@ -495,6 +522,12 @@ public:
|
|||
static bool
|
||||
IsFloatingPointType (void *clang_type, uint32_t &count, bool &is_complex);
|
||||
|
||||
static bool
|
||||
IsCXXClassType (void *clang_type);
|
||||
|
||||
static bool
|
||||
IsObjCClassType (void *clang_type);
|
||||
|
||||
//static bool
|
||||
//ConvertFloatValueToString (clang::ASTContext *ast_context,
|
||||
// void *clang_type,
|
||||
|
|
|
@ -2432,6 +2432,7 @@
|
|||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
|
|
|
@ -1206,12 +1206,18 @@ ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
|
|||
false,
|
||||
ClangASTContext::GetTypeQualifiers(copied_type));
|
||||
|
||||
ClangASTContext::AddMethodToCXXRecordType(parser_ast_context,
|
||||
copied_type,
|
||||
"___clang_expr",
|
||||
method_type,
|
||||
lldb::eAccessPublic,
|
||||
false);
|
||||
const bool is_virtual = false;
|
||||
const bool is_static = false;
|
||||
const bool is_inline = false;
|
||||
|
||||
ClangASTContext::AddMethodToCXXRecordType (parser_ast_context,
|
||||
copied_type,
|
||||
"___clang_expr",
|
||||
method_type,
|
||||
lldb::eAccessPublic,
|
||||
is_virtual,
|
||||
is_static,
|
||||
is_inline);
|
||||
}
|
||||
|
||||
context.AddTypeDecl(copied_type);
|
||||
|
|
|
@ -476,7 +476,7 @@ SymbolFileDWARF::DebugRanges() const
|
|||
}
|
||||
|
||||
bool
|
||||
SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit* cu, CompUnitSP& compile_unit_sp)
|
||||
SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* cu, CompUnitSP& compile_unit_sp)
|
||||
{
|
||||
if (cu != NULL)
|
||||
{
|
||||
|
@ -566,7 +566,7 @@ AddRangesToBlock
|
|||
|
||||
|
||||
Function *
|
||||
SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
|
||||
SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
|
||||
{
|
||||
DWARFDebugRanges::RangeList func_ranges;
|
||||
const char *name = NULL;
|
||||
|
@ -641,7 +641,7 @@ SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)
|
|||
{
|
||||
assert (sc.comp_unit);
|
||||
size_t functions_added = 0;
|
||||
const DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
|
||||
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
|
||||
if (dwarf_cu)
|
||||
{
|
||||
DWARFDIECollection function_dies;
|
||||
|
@ -894,7 +894,7 @@ SymbolFileDWARF::ParseFunctionBlocks
|
|||
(
|
||||
const SymbolContext& sc,
|
||||
Block *parent_block,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
addr_t subprogram_low_pc,
|
||||
bool parse_siblings,
|
||||
|
@ -1011,7 +1011,7 @@ SymbolFileDWARF::ParseChildMembers
|
|||
(
|
||||
const SymbolContext& sc,
|
||||
TypeSP& type_sp,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *parent_die,
|
||||
void *class_clang_type,
|
||||
const LanguageType class_language,
|
||||
|
@ -1107,135 +1107,8 @@ SymbolFileDWARF::ParseChildMembers
|
|||
break;
|
||||
|
||||
case DW_TAG_subprogram:
|
||||
{
|
||||
DWARFDebugInfoEntry::Attributes attributes;
|
||||
is_a_class = true;
|
||||
if (default_accessibility == eAccessNone)
|
||||
default_accessibility = eAccessPrivate;
|
||||
|
||||
//printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
|
||||
// Set a bit that lets us know that we are currently parsing this
|
||||
const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
|
||||
|
||||
const char *mangled = NULL;
|
||||
dw_offset_t type_die_offset = DW_INVALID_OFFSET;
|
||||
Declaration decl;
|
||||
bool is_variadic = false;
|
||||
bool is_inline = false;
|
||||
bool is_virtual = false;
|
||||
unsigned type_quals = 0;
|
||||
AccessType accessibility = default_accessibility;
|
||||
|
||||
clang::FunctionDecl::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
|
||||
const char *type_name_cstr = NULL;
|
||||
ConstString type_name_dbstr;
|
||||
|
||||
|
||||
const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
|
||||
if (num_attributes > 0)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i=0; i<num_attributes; ++i)
|
||||
{
|
||||
const dw_attr_t attr = attributes.AttributeAtIndex(i);
|
||||
DWARFFormValue form_value;
|
||||
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
|
||||
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
|
||||
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
|
||||
case DW_AT_name:
|
||||
type_name_cstr = form_value.AsCString(&get_debug_str_data());
|
||||
break;
|
||||
|
||||
case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
|
||||
case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
|
||||
case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
|
||||
//case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
|
||||
case DW_AT_external:
|
||||
if (form_value.Unsigned())
|
||||
{
|
||||
if (storage == clang::SC_None)
|
||||
storage = clang::SC_Extern;
|
||||
else
|
||||
storage = clang::SC_PrivateExtern;
|
||||
}
|
||||
break;
|
||||
case DW_AT_inline:
|
||||
is_inline = form_value.Unsigned() != 0;
|
||||
break;
|
||||
|
||||
|
||||
case DW_AT_virtuality:
|
||||
is_virtual = form_value.Unsigned() != 0;
|
||||
break;
|
||||
|
||||
case DW_AT_allocated:
|
||||
case DW_AT_associated:
|
||||
case DW_AT_address_class:
|
||||
case DW_AT_artificial:
|
||||
case DW_AT_calling_convention:
|
||||
case DW_AT_data_location:
|
||||
case DW_AT_elemental:
|
||||
case DW_AT_entry_pc:
|
||||
case DW_AT_explicit:
|
||||
case DW_AT_frame_base:
|
||||
case DW_AT_high_pc:
|
||||
case DW_AT_low_pc:
|
||||
case DW_AT_object_pointer:
|
||||
case DW_AT_prototyped:
|
||||
case DW_AT_pure:
|
||||
case DW_AT_ranges:
|
||||
case DW_AT_recursive:
|
||||
case DW_AT_return_addr:
|
||||
case DW_AT_segment:
|
||||
case DW_AT_specification:
|
||||
case DW_AT_start_scope:
|
||||
case DW_AT_static_link:
|
||||
case DW_AT_trampoline:
|
||||
case DW_AT_visibility:
|
||||
case DW_AT_vtable_elem_location:
|
||||
case DW_AT_abstract_origin:
|
||||
case DW_AT_description:
|
||||
case DW_AT_sibling:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *return_clang_type = NULL;
|
||||
Type *func_type = ResolveTypeUID(type_die_offset);
|
||||
if (func_type)
|
||||
return_clang_type = func_type->GetOpaqueClangQualType();
|
||||
else
|
||||
return_clang_type = type_list->GetClangASTContext().GetBuiltInType_void();
|
||||
|
||||
std::vector<void *> function_param_types;
|
||||
std::vector<clang::ParmVarDecl*> function_param_decls;
|
||||
|
||||
// Parse the function children for the parameters
|
||||
bool skip_artificial = true;
|
||||
|
||||
ParseChildParameters (sc, type_sp, dwarf_cu, die, skip_artificial, type_list, function_param_types, function_param_decls);
|
||||
|
||||
void *method_function_proto = type_list->GetClangASTContext().CreateFunctionType (return_clang_type, &function_param_types[0], function_param_types.size(), is_variadic, type_quals);
|
||||
if (type_name_cstr)
|
||||
{
|
||||
clang::CXXMethodDecl *method_decl = type_list->GetClangASTContext().AddMethodToCXXRecordType (class_clang_type,
|
||||
type_name_cstr,
|
||||
method_function_proto,
|
||||
accessibility,
|
||||
is_virtual);
|
||||
assert (method_decl);
|
||||
//m_die_to_decl_ctx[die] = method_decl;
|
||||
}
|
||||
|
||||
const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
|
||||
assert(type_sp.get());
|
||||
}
|
||||
}
|
||||
// Let the type parsing code handle this one for us...
|
||||
ResolveType (dwarf_cu, die);
|
||||
break;
|
||||
|
||||
case DW_TAG_inheritance:
|
||||
|
@ -1376,7 +1249,7 @@ SymbolFileDWARF::ResolveType (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* t
|
|||
}
|
||||
|
||||
CompileUnit*
|
||||
SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit* cu, uint32_t cu_idx)
|
||||
SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* cu, uint32_t cu_idx)
|
||||
{
|
||||
// Check if the symbol vendor already knows about this compile unit?
|
||||
if (cu->GetUserData() == NULL)
|
||||
|
@ -2026,7 +1899,7 @@ SymbolFileDWARF::ParseChildParameters
|
|||
(
|
||||
const SymbolContext& sc,
|
||||
TypeSP& type_sp,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *parent_die,
|
||||
bool skip_artificial,
|
||||
TypeList* type_list,
|
||||
|
@ -2100,17 +1973,36 @@ SymbolFileDWARF::ParseChildParameters
|
|||
}
|
||||
}
|
||||
|
||||
if (skip_artificial && is_artificial)
|
||||
continue;
|
||||
|
||||
Type *dc_type = ResolveTypeUID(param_type_die_offset);
|
||||
if (dc_type)
|
||||
bool skip = false;
|
||||
if (skip_artificial)
|
||||
{
|
||||
function_param_types.push_back (dc_type->GetOpaqueClangQualType());
|
||||
if (is_artificial)
|
||||
skip = true;
|
||||
else
|
||||
{
|
||||
|
||||
clang::ParmVarDecl *param_var_decl = type_list->GetClangASTContext().CreateParameterDeclaration (name, dc_type->GetOpaqueClangQualType(), storage);
|
||||
assert(param_var_decl);
|
||||
function_param_decls.push_back(param_var_decl);
|
||||
// HACK: Objective C formal parameters "self" and "_cmd"
|
||||
// are not marked as artificial in the DWARF...
|
||||
CompileUnit *cu = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
|
||||
if (cu && (cu->GetLanguage() == eLanguageTypeObjC || cu->GetLanguage() == eLanguageTypeObjC_plus_plus))
|
||||
{
|
||||
if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0))
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
Type *type = ResolveTypeUID(param_type_die_offset);
|
||||
if (type)
|
||||
{
|
||||
function_param_types.push_back (type->GetOpaqueClangQualType());
|
||||
|
||||
clang::ParmVarDecl *param_var_decl = type_list->GetClangASTContext().CreateParameterDeclaration (name, type->GetOpaqueClangQualType(), storage);
|
||||
assert(param_var_decl);
|
||||
function_param_decls.push_back(param_var_decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2130,7 +2022,7 @@ SymbolFileDWARF::ParseChildEnumerators
|
|||
TypeSP& type_sp,
|
||||
void * enumerator_qual_type,
|
||||
uint32_t enumerator_byte_size,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *parent_die
|
||||
)
|
||||
{
|
||||
|
@ -2200,7 +2092,7 @@ void
|
|||
SymbolFileDWARF::ParseChildArrayInfo
|
||||
(
|
||||
const SymbolContext& sc,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *parent_die,
|
||||
int64_t& first_index,
|
||||
std::vector<uint64_t>& element_orders,
|
||||
|
@ -2406,7 +2298,7 @@ SymbolFileDWARF::GetClangDeclContextForDIEOffset (dw_offset_t die_offset)
|
|||
|
||||
|
||||
clang::DeclContext *
|
||||
SymbolFileDWARF::GetClangDeclContextForDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
|
||||
SymbolFileDWARF::GetClangDeclContextForDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
|
||||
{
|
||||
DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
|
||||
if (pos != m_die_to_decl_ctx.end())
|
||||
|
@ -2450,14 +2342,14 @@ SymbolFileDWARF::GetClangDeclContextForDIE (const DWARFCompileUnit *cu, const DW
|
|||
}
|
||||
|
||||
TypeSP
|
||||
SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new)
|
||||
SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new)
|
||||
{
|
||||
TypeSP type_sp;
|
||||
|
||||
AccessType accessibility = eAccessNone;
|
||||
if (die != NULL)
|
||||
{
|
||||
dw_tag_t tag = die->Tag();
|
||||
const dw_tag_t tag = die->Tag();
|
||||
if (die->GetUserData() == NULL)
|
||||
{
|
||||
type_is_new = true;
|
||||
|
@ -2840,6 +2732,9 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
Declaration decl;
|
||||
bool is_variadic = false;
|
||||
bool is_inline = false;
|
||||
bool is_static = false;
|
||||
bool is_virtual = false;
|
||||
|
||||
unsigned type_quals = 0;
|
||||
clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
|
||||
|
||||
|
@ -2850,7 +2745,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
uint32_t i;
|
||||
for (i=0; i<num_attributes; ++i)
|
||||
{
|
||||
attr = attributes.AttributeAtIndex(i);
|
||||
const dw_attr_t attr = attributes.AttributeAtIndex(i);
|
||||
DWARFFormValue form_value;
|
||||
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
|
||||
{
|
||||
|
@ -2868,6 +2763,8 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
|
||||
case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
|
||||
case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
|
||||
case DW_AT_inline: is_inline = form_value.Unsigned() != 0; break;
|
||||
case DW_AT_virtuality: is_virtual = form_value.Unsigned() != 0; break;
|
||||
case DW_AT_external:
|
||||
if (form_value.Unsigned())
|
||||
{
|
||||
|
@ -2877,9 +2774,6 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
storage = clang::SC_PrivateExtern;
|
||||
}
|
||||
break;
|
||||
case DW_AT_inline:
|
||||
is_inline = form_value.Unsigned() != 0;
|
||||
break;
|
||||
|
||||
case DW_AT_allocated:
|
||||
case DW_AT_associated:
|
||||
|
@ -2905,7 +2799,6 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
case DW_AT_static_link:
|
||||
case DW_AT_trampoline:
|
||||
case DW_AT_visibility:
|
||||
case DW_AT_virtuality:
|
||||
case DW_AT_vtable_elem_location:
|
||||
case DW_AT_abstract_origin:
|
||||
case DW_AT_description:
|
||||
|
@ -2926,18 +2819,92 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
std::vector<clang::ParmVarDecl*> function_param_decls;
|
||||
|
||||
// Parse the function children for the parameters
|
||||
bool skip_artificial = false;
|
||||
ParseChildParameters(sc, type_sp, dwarf_cu, die, skip_artificial, type_list, function_param_types, function_param_decls);
|
||||
bool skip_artificial = true;
|
||||
ParseChildParameters (sc, type_sp, dwarf_cu, die, skip_artificial, type_list, function_param_types, function_param_decls);
|
||||
|
||||
// clang_type will get the function prototype clang type after this call
|
||||
clang_type = type_list->GetClangASTContext().CreateFunctionType (return_clang_type, &function_param_types[0], function_param_types.size(), is_variadic, type_quals);
|
||||
if (type_name_cstr)
|
||||
{
|
||||
clang::FunctionDecl *function_decl = type_list->GetClangASTContext().CreateFunctionDeclaration (type_name_cstr, clang_type, storage, is_inline);
|
||||
// Add the decl to our DIE to decl context map
|
||||
assert (function_decl);
|
||||
m_die_to_decl_ctx[die] = function_decl;
|
||||
if (!function_param_decls.empty())
|
||||
type_list->GetClangASTContext().SetFunctionParameters (function_decl, &function_param_decls.front(), function_param_decls.size());
|
||||
bool type_handled = false;
|
||||
const DWARFDebugInfoEntry *parent_die = die->GetParent();
|
||||
if (tag == DW_TAG_subprogram)
|
||||
{
|
||||
if (type_name_cstr[1] == '[' && (type_name_cstr[0] == '-' || type_name_cstr[0] == '+'))
|
||||
{
|
||||
// We need to find the DW_TAG_class_type or
|
||||
// DW_TAG_struct_type by name so we can add this
|
||||
// as a member function of the class.
|
||||
const char *class_name_start = type_name_cstr + 2;
|
||||
const char *class_name_end = ::strchr (class_name_start, ' ');
|
||||
SymbolContext empty_sc;
|
||||
void *class_opaque_type = NULL;
|
||||
if (class_name_start < class_name_end)
|
||||
{
|
||||
ConstString class_name (class_name_start, class_name_end - class_name_start);
|
||||
TypeList types;
|
||||
const uint32_t match_count = FindTypes (empty_sc, class_name, true, UINT32_MAX, types);
|
||||
if (match_count > 0)
|
||||
{
|
||||
for (uint32_t i=0; i<match_count; ++i)
|
||||
{
|
||||
Type *type = types.GetTypeAtIndex (i).get();
|
||||
if (ClangASTContext::IsObjCClassType (type->GetOpaqueClangQualType()))
|
||||
{
|
||||
class_opaque_type = type->GetOpaqueClangQualType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (class_opaque_type)
|
||||
{
|
||||
clang::ObjCMethodDecl *objc_method_decl;
|
||||
objc_method_decl = type_list->GetClangASTContext().AddMethodToObjCObjectType (class_opaque_type,
|
||||
type_name_cstr,
|
||||
clang_type,
|
||||
accessibility);
|
||||
type_handled = objc_method_decl != NULL;
|
||||
}
|
||||
}
|
||||
else if (parent_die->Tag() == DW_TAG_class_type ||
|
||||
parent_die->Tag() == DW_TAG_structure_type)
|
||||
{
|
||||
// Look at the parent of this DIE and see if is is
|
||||
// a class or struct and see if this is actually a
|
||||
// C++ method
|
||||
Type *class_type = ResolveType (dwarf_cu, parent_die);
|
||||
if (class_type)
|
||||
{
|
||||
void *class_opaque_type = class_type->GetOpaqueClangQualType ();
|
||||
if (ClangASTContext::IsCXXClassType (class_opaque_type))
|
||||
{
|
||||
clang::CXXMethodDecl *cxx_method_decl;
|
||||
cxx_method_decl = type_list->GetClangASTContext().AddMethodToCXXRecordType (class_opaque_type,
|
||||
type_name_cstr,
|
||||
clang_type,
|
||||
accessibility,
|
||||
is_virtual,
|
||||
is_static,
|
||||
is_inline);
|
||||
type_handled = cxx_method_decl != NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!type_handled)
|
||||
{
|
||||
// We just have a function that isn't part of a class
|
||||
clang::FunctionDecl *function_decl = type_list->GetClangASTContext().CreateFunctionDeclaration (type_name_cstr, clang_type, storage, is_inline);
|
||||
|
||||
// Add the decl to our DIE to decl context map
|
||||
assert (function_decl);
|
||||
m_die_to_decl_ctx[die] = function_decl;
|
||||
if (!function_param_decls.empty())
|
||||
type_list->GetClangASTContext().SetFunctionParameters (function_decl, &function_param_decls.front(), function_param_decls.size());
|
||||
}
|
||||
}
|
||||
type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, 0, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
|
||||
|
||||
|
@ -3154,7 +3121,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
}
|
||||
|
||||
size_t
|
||||
SymbolFileDWARF::ParseTypes (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children)
|
||||
SymbolFileDWARF::ParseTypes (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children)
|
||||
{
|
||||
size_t types_added = 0;
|
||||
while (die != NULL)
|
||||
|
@ -3296,7 +3263,7 @@ VariableSP
|
|||
SymbolFileDWARF::ParseVariableDIE
|
||||
(
|
||||
const SymbolContext& sc,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
const lldb::addr_t func_low_pc
|
||||
)
|
||||
|
@ -3439,7 +3406,7 @@ size_t
|
|||
SymbolFileDWARF::ParseVariables
|
||||
(
|
||||
const SymbolContext& sc,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const lldb::addr_t func_low_pc,
|
||||
const DWARFDebugInfoEntry *orig_die,
|
||||
bool parse_siblings,
|
||||
|
|
|
@ -162,7 +162,7 @@ public:
|
|||
SupportedVersion(uint16_t version);
|
||||
|
||||
clang::DeclContext *
|
||||
GetClangDeclContextForDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
|
||||
GetClangDeclContextForDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
|
||||
|
||||
clang::DeclContext *
|
||||
GetClangDeclContextForDIEOffset (dw_offset_t die_offset);
|
||||
|
@ -200,31 +200,31 @@ protected:
|
|||
};
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
|
||||
bool ParseCompileUnit(DWARFCompileUnit* cu, lldb::CompUnitSP& compile_unit_sp);
|
||||
bool ParseCompileUnit (DWARFCompileUnit* cu, lldb::CompUnitSP& compile_unit_sp);
|
||||
DWARFCompileUnit* GetDWARFCompileUnitForUID(lldb::user_id_t cu_uid);
|
||||
DWARFCompileUnit* GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu);
|
||||
lldb_private::CompileUnit* GetCompUnitForDWARFCompUnit(DWARFCompileUnit* cu, uint32_t cu_idx = UINT32_MAX);
|
||||
bool GetFunction (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc);
|
||||
lldb_private::Function * ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die);
|
||||
lldb_private::Function * ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die);
|
||||
size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
|
||||
lldb_private::Block *parent_block,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
lldb::addr_t subprogram_low_pc,
|
||||
bool parse_siblings,
|
||||
bool parse_children);
|
||||
size_t ParseTypes (const lldb_private::SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children);
|
||||
lldb::TypeSP ParseType (const lldb_private::SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new);
|
||||
size_t ParseTypes (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children);
|
||||
lldb::TypeSP ParseType (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new);
|
||||
|
||||
lldb::VariableSP ParseVariableDIE(
|
||||
const lldb_private::SymbolContext& sc,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
const lldb::addr_t func_low_pc);
|
||||
|
||||
size_t ParseVariables(
|
||||
const lldb_private::SymbolContext& sc,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const lldb::addr_t func_low_pc,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
bool parse_siblings,
|
||||
|
@ -234,7 +234,7 @@ protected:
|
|||
size_t ParseChildMembers(
|
||||
const lldb_private::SymbolContext& sc,
|
||||
lldb::TypeSP& type_sp,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
void *class_clang_type,
|
||||
const lldb::LanguageType class_language,
|
||||
|
@ -246,7 +246,7 @@ protected:
|
|||
size_t ParseChildParameters(
|
||||
const lldb_private::SymbolContext& sc,
|
||||
lldb::TypeSP& type_sp,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *parent_die,
|
||||
bool skip_artificial,
|
||||
lldb_private::TypeList* type_list,
|
||||
|
@ -258,12 +258,12 @@ protected:
|
|||
lldb::TypeSP& type_sp,
|
||||
void *enumerator_qual_type,
|
||||
uint32_t enumerator_byte_size,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *enum_die);
|
||||
|
||||
void ParseChildArrayInfo(
|
||||
const lldb_private::SymbolContext& sc,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *parent_die,
|
||||
int64_t& first_index,
|
||||
std::vector<uint64_t>& element_orders,
|
||||
|
|
|
@ -811,7 +811,9 @@ ClangASTContext::AddMethodToCXXRecordType
|
|||
const char *name,
|
||||
void *method_opaque_type,
|
||||
lldb::AccessType access,
|
||||
bool is_virtual
|
||||
bool is_virtual,
|
||||
bool is_static,
|
||||
bool is_inline
|
||||
)
|
||||
{
|
||||
if (!record_opaque_type || !method_opaque_type || !name)
|
||||
|
@ -824,51 +826,56 @@ ClangASTContext::AddMethodToCXXRecordType
|
|||
assert(identifier_table);
|
||||
|
||||
QualType record_qual_type(QualType::getFromOpaquePtr(record_opaque_type));
|
||||
clang::Type *record_type(record_qual_type.getTypePtr());
|
||||
|
||||
clang::Type *clang_type(record_qual_type.getTypePtr());
|
||||
|
||||
if (!record_type)
|
||||
if (clang_type == NULL)
|
||||
return NULL;
|
||||
|
||||
RecordType *record_recty(dyn_cast<RecordType>(record_type));
|
||||
RecordType *record_clang_type(dyn_cast<RecordType>(clang_type));
|
||||
|
||||
if (!record_recty)
|
||||
if (record_clang_type == NULL)
|
||||
return NULL;
|
||||
|
||||
RecordDecl *record_decl = record_recty->getDecl();
|
||||
RecordDecl *record_decl = record_clang_type->getDecl();
|
||||
|
||||
if (!record_decl)
|
||||
if (record_decl == NULL)
|
||||
return NULL;
|
||||
|
||||
CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
|
||||
|
||||
if (!cxx_record_decl)
|
||||
if (cxx_record_decl == NULL)
|
||||
return NULL;
|
||||
|
||||
QualType method_qual_type(QualType::getFromOpaquePtr(method_opaque_type));
|
||||
QualType method_qual_type (QualType::getFromOpaquePtr (method_opaque_type));
|
||||
|
||||
CXXMethodDecl *cxx_method_decl = CXXMethodDecl::Create(*ast_context,
|
||||
cxx_record_decl,
|
||||
DeclarationNameInfo(DeclarationName(&identifier_table->get(name)), SourceLocation()),
|
||||
method_qual_type,
|
||||
NULL);
|
||||
CXXMethodDecl *cxx_method_decl = CXXMethodDecl::Create (*ast_context,
|
||||
cxx_record_decl,
|
||||
DeclarationNameInfo (DeclarationName (&identifier_table->get(name)), SourceLocation()),
|
||||
method_qual_type,
|
||||
NULL, // TypeSourceInfo *
|
||||
is_static,
|
||||
SC_None,
|
||||
is_inline);
|
||||
|
||||
clang::AccessSpecifier AS = ConvertAccessTypeToAccessSpecifier(access);
|
||||
|
||||
cxx_method_decl->setAccess(AS);
|
||||
cxx_method_decl->setVirtualAsWritten(is_virtual);
|
||||
clang::AccessSpecifier access_specifier = ConvertAccessTypeToAccessSpecifier (access);
|
||||
|
||||
cxx_method_decl->setAccess (access_specifier);
|
||||
cxx_method_decl->setVirtualAsWritten (is_virtual);
|
||||
|
||||
// Populate the method decl with parameter decls
|
||||
clang::Type *method_type(method_qual_type.getTypePtr());
|
||||
|
||||
if (!method_type)
|
||||
if (method_type == NULL)
|
||||
return NULL;
|
||||
|
||||
FunctionProtoType *method_funprototy(dyn_cast<FunctionProtoType>(method_type));
|
||||
FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(method_type));
|
||||
|
||||
if (!method_funprototy)
|
||||
if (!method_function_prototype)
|
||||
return NULL;
|
||||
|
||||
unsigned int num_params = method_funprototy->getNumArgs();
|
||||
unsigned int num_params = method_function_prototype->getNumArgs();
|
||||
|
||||
ParmVarDecl *params[num_params];
|
||||
|
||||
|
@ -876,20 +883,20 @@ ClangASTContext::AddMethodToCXXRecordType
|
|||
param_index < num_params;
|
||||
++param_index)
|
||||
{
|
||||
params[param_index] = ParmVarDecl::Create(*ast_context,
|
||||
cxx_method_decl,
|
||||
SourceLocation(),
|
||||
NULL, // anonymous
|
||||
method_funprototy->getArgType(param_index),
|
||||
NULL,
|
||||
SC_Auto,
|
||||
SC_Auto,
|
||||
NULL);
|
||||
params[param_index] = ParmVarDecl::Create (*ast_context,
|
||||
cxx_method_decl,
|
||||
SourceLocation(),
|
||||
NULL, // anonymous
|
||||
method_function_prototype->getArgType(param_index),
|
||||
NULL,
|
||||
SC_None,
|
||||
SC_None,
|
||||
NULL);
|
||||
}
|
||||
|
||||
cxx_method_decl->setParams(params, num_params);
|
||||
cxx_method_decl->setParams (params, num_params);
|
||||
|
||||
cxx_record_decl->addDecl(cxx_method_decl);
|
||||
cxx_record_decl->addDecl (cxx_method_decl);
|
||||
|
||||
return cxx_method_decl;
|
||||
}
|
||||
|
@ -988,14 +995,14 @@ ClangASTContext::AddFieldToRecordType
|
|||
ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(clang_type);
|
||||
if (objc_class_type)
|
||||
{
|
||||
bool isSynthesized = false;
|
||||
bool is_synthesized = false;
|
||||
ClangASTContext::AddObjCClassIVar (ast_context,
|
||||
record_clang_type,
|
||||
name,
|
||||
field_type,
|
||||
access,
|
||||
bitfield_bit_size,
|
||||
isSynthesized);
|
||||
is_synthesized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1250,7 +1257,7 @@ ClangASTContext::AddObjCClassIVar
|
|||
void *ivar_opaque_type,
|
||||
AccessType access,
|
||||
uint32_t bitfield_bit_size,
|
||||
bool isSynthesized
|
||||
bool is_synthesized
|
||||
)
|
||||
{
|
||||
if (class_opaque_type == NULL || ivar_opaque_type == NULL)
|
||||
|
@ -1289,7 +1296,7 @@ ClangASTContext::AddObjCClassIVar
|
|||
NULL, // TypeSourceInfo *
|
||||
ConvertAccessTypeToObjCIvarAccessControl (access),
|
||||
bit_width,
|
||||
isSynthesized);
|
||||
is_synthesized);
|
||||
|
||||
if (field)
|
||||
{
|
||||
|
@ -1334,7 +1341,132 @@ ClangASTContext::ObjCDeclHasIVars (ObjCInterfaceDecl *class_interface_decl, bool
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
clang::ObjCMethodDecl *
|
||||
ClangASTContext::AddMethodToObjCObjectType
|
||||
(
|
||||
clang::ASTContext *ast_context,
|
||||
void *class_opaque_type,
|
||||
const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
|
||||
void *method_opaque_type,
|
||||
lldb::AccessType access
|
||||
)
|
||||
{
|
||||
if (class_opaque_type == NULL || method_opaque_type == NULL)
|
||||
return NULL;
|
||||
|
||||
IdentifierTable *identifier_table = &ast_context->Idents;
|
||||
|
||||
assert (ast_context != NULL);
|
||||
assert (identifier_table != NULL);
|
||||
|
||||
QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type));
|
||||
|
||||
clang::Type *class_type = class_qual_type.getTypePtr();
|
||||
if (class_type == NULL)
|
||||
return NULL;
|
||||
|
||||
ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type);
|
||||
|
||||
if (objc_class_type == NULL)
|
||||
return NULL;
|
||||
|
||||
ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
|
||||
if (class_interface_decl == NULL)
|
||||
return NULL;
|
||||
|
||||
const char *selector_start = ::strchr (name, ' ');
|
||||
if (selector_start == NULL)
|
||||
return NULL;
|
||||
|
||||
selector_start++;
|
||||
if (!(::isalpha (selector_start[0]) || selector_start[0] == '_'))
|
||||
return NULL;
|
||||
llvm::SmallVector<IdentifierInfo *, 12> selector_idents;
|
||||
|
||||
size_t len;
|
||||
const char *start;
|
||||
for (start = selector_start, len = ::strcspn(start, ":]");
|
||||
start && *start != '\0' && *start != ']';
|
||||
start += len + 1)
|
||||
{
|
||||
selector_idents.push_back (&identifier_table->get (StringRef (start, len)));
|
||||
}
|
||||
|
||||
|
||||
if (selector_idents.size() == 0)
|
||||
return 0;
|
||||
|
||||
clang::Selector method_selector = ast_context->Selectors.getSelector (selector_idents.size(),
|
||||
selector_idents.data());
|
||||
|
||||
QualType method_qual_type (QualType::getFromOpaquePtr (method_opaque_type));
|
||||
|
||||
// Populate the method decl with parameter decls
|
||||
clang::Type *method_type(method_qual_type.getTypePtr());
|
||||
|
||||
if (method_type == NULL)
|
||||
return NULL;
|
||||
|
||||
FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(method_type));
|
||||
|
||||
if (!method_function_prototype)
|
||||
return NULL;
|
||||
|
||||
|
||||
bool is_variadic = false;
|
||||
bool is_synthesized = false;
|
||||
bool is_defined = false;
|
||||
ObjCMethodDecl::ImplementationControl imp_control = ObjCMethodDecl::None;
|
||||
|
||||
const unsigned num_args = method_function_prototype->getNumArgs();
|
||||
|
||||
ObjCMethodDecl *objc_method_decl = ObjCMethodDecl::Create (*ast_context,
|
||||
SourceLocation(), // beginLoc,
|
||||
SourceLocation(), // endLoc,
|
||||
method_selector,
|
||||
method_function_prototype->getResultType(),
|
||||
NULL, // TypeSourceInfo *ResultTInfo,
|
||||
GetDeclContextForType (class_opaque_type),
|
||||
name[0] == '-',
|
||||
is_variadic,
|
||||
is_synthesized,
|
||||
is_defined,
|
||||
imp_control,
|
||||
num_args);
|
||||
|
||||
|
||||
if (objc_method_decl == NULL)
|
||||
return NULL;
|
||||
|
||||
if (num_args > 0)
|
||||
{
|
||||
llvm::SmallVector<ParmVarDecl *, 12> params;
|
||||
|
||||
for (int param_index = 0; param_index < num_args; ++param_index)
|
||||
{
|
||||
params.push_back (ParmVarDecl::Create (*ast_context,
|
||||
objc_method_decl,
|
||||
SourceLocation(),
|
||||
NULL, // anonymous
|
||||
method_function_prototype->getArgType(param_index),
|
||||
NULL,
|
||||
SC_Auto,
|
||||
SC_Auto,
|
||||
NULL));
|
||||
}
|
||||
|
||||
objc_method_decl->setMethodParams(*ast_context, params.data(), params.size(), num_args);
|
||||
}
|
||||
|
||||
class_interface_decl->addDecl (objc_method_decl);
|
||||
|
||||
|
||||
return objc_method_decl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark Aggregate Types
|
||||
|
||||
|
@ -3044,6 +3176,32 @@ ClangASTContext::IsFloatingPointType (void *clang_type, uint32_t &count, bool &i
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ClangASTContext::IsCXXClassType (void *clang_type)
|
||||
{
|
||||
if (clang_type)
|
||||
{
|
||||
QualType qual_type (QualType::getFromOpaquePtr(clang_type));
|
||||
if (qual_type->getAsCXXRecordDecl() != NULL)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ClangASTContext::IsObjCClassType (void *clang_type)
|
||||
{
|
||||
if (clang_type)
|
||||
{
|
||||
QualType qual_type (QualType::getFromOpaquePtr(clang_type));
|
||||
if (qual_type->isObjCObjectOrInterfaceType())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ClangASTContext::IsCStringType (void *clang_type, uint32_t &length)
|
||||
|
|
Loading…
Reference in New Issue